A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
attribute-container-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Caliola Engineering, LLC.
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Jared Dulmage <jared.dulmage@caliola.com>
7 */
8
9#include "ns3/attribute-container.h"
10#include "ns3/double.h"
11#include "ns3/integer.h"
12#include "ns3/log.h"
13#include "ns3/object.h"
14#include "ns3/pair.h"
15#include "ns3/ptr.h"
16#include "ns3/string.h"
17#include "ns3/test.h"
18#include "ns3/tuple.h"
19#include "ns3/type-id.h"
20#include "ns3/uinteger.h"
21
22#include <algorithm>
23#include <list>
24#include <map>
25#include <utility>
26#include <vector>
27
28using namespace ns3;
29
30NS_LOG_COMPONENT_DEFINE("AttributeContainerTestSuite");
31
32/**
33 * @file
34 * @ingroup attribute-tests
35 * Attribute container test suite
36 */
37
38/**
39 * @ingroup attribute-tests
40 * Attribute container object.
41 */
43{
44 public:
47
48 /**
49 * Reverses the list of doubles.
50 */
51 void ReverseDoubleList();
52
53 /**
54 * @brief Get the type ID.
55 * @return The object TypeId.
56 */
57 static TypeId GetTypeId();
58
59 /**
60 * Set the list of doubles to the given list
61 *
62 * @param doubleList the given list
63 */
64 void SetDoubleList(const std::list<double>& doubleList);
65 /**
66 * Get the list of doubles
67 *
68 * @return the list of doubles
69 */
70 std::list<double> GetDoubleList() const;
71
72 /**
73 * Set the vector of ints to the given vector
74 *
75 * @param vec the given vector
76 */
77 void SetIntVec(std::vector<int> vec);
78 /**
79 * Get the vector of ints
80 *
81 * @return the vector of ints
82 */
83 std::vector<int> GetIntVec() const;
84
85 private:
86 std::list<double> m_doublelist; //!< List of doubles.
87 std::vector<int> m_intvec; //!< Vector of ints.
88 // TODO(jared): need PairValue attributevalue to handle std::pair elements
89 std::map<std::string, int> m_map; //!< Map of <std::string, int>.
90 std::map<int64_t, std::list<int64_t>> m_intVecIntMapping; //!< Mapping integers to vectors
91};
92
96
100
101TypeId
103{
105
106 static TypeId tid =
107 TypeId("ns3::AttributeContainerObject")
108 .SetParent<Object>()
109 .SetGroupName("Test")
110 .AddConstructor<AttributeContainerObject>()
111 .AddAttribute("DoubleList",
112 "List of doubles",
117 .AddAttribute(
118 "IntegerVector",
119 "Vector of integers",
120 // the container value container differs from the underlying object
122 // the type of the underlying container cannot be deduced
127 .AddAttribute(
128 "MapStringInt",
129 "Map of strings to ints",
130 // the container value container differs from the underlying object
137 .AddAttribute(
138 "IntVecPairVec",
139 "An example of complex attribute that is defined by a vector of pairs consisting "
140 "of an integer value and a vector of integers. In case a string is used to set "
141 "this attribute, the string shall contain the pairs separated by a semicolon (;); "
142 "in every pair, the integer value and the vector of integers are separated by a "
143 "blank space, and the elements of the vectors are separated by a comma (,) "
144 "without spaces. E.g. \"0 1,2,3; 1 0; 2 0,1\" consists of three pairs containing "
145 "vectors of 3, 1 and 2 elements, respectively.",
146 StringValue(""),
147 MakeAttributeContainerAccessor<IntVecMapValue, ';'>(
149 MakeAttributeContainerChecker<IntVecMapValue, ';'>(
153 return tid;
154}
155
156void
161
162void
163AttributeContainerObject::SetDoubleList(const std::list<double>& doubleList)
164{
165 m_doublelist = doubleList;
166}
167
168std::list<double>
173
174void
176{
177 m_intvec = vec;
178}
179
180std::vector<int>
182{
183 return m_intvec;
184}
185
186/**
187 * @ingroup attribute-tests
188 *
189 * Test AttributeContainer instantiation, initialization, access
190 */
192{
193 public:
195
197 {
198 }
199
200 private:
201 void DoRun() override;
202};
203
205 : TestCase("test instantiation, initialization, access")
206{
207}
208
209void
211{
212 {
213 std::list<double> ref = {1.0, 2.1, 3.145269};
214
216
217 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
218 auto aciter = ac.Begin();
219 for (auto rend = ref.end(), riter = ref.begin(); riter != rend; ++riter)
220 {
221 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
222 NS_TEST_ASSERT_MSG_EQ(*riter, (*aciter)->Get(), "Incorrect value");
223 ++aciter;
224 }
225 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
226 }
227
228 {
229 std::vector<int> ref = {-2, 3, 10, -1042};
230
231 AttributeContainerValue<IntegerValue> ac(ref.begin(), ref.end());
232
233 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
234 auto aciter = ac.Begin();
235 for (auto rend = ref.end(), riter = ref.begin(); riter != rend; ++riter)
236 {
237 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
238 NS_TEST_ASSERT_MSG_EQ(*riter, (*aciter)->Get(), "Incorrect value");
239 ++aciter;
240 }
241 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
242 }
243
244 {
245 auto ref = {"one", "two", "three"};
246 AttributeContainerValue<StringValue> ac(ref.begin(), ref.end());
247
248 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
249 auto aciter = ac.Begin();
250 for (auto v : ref)
251 {
252 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
253 NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value");
254 ++aciter;
255 }
256 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
257 }
258
259 {
260 auto ref = {"one", "two", "three"};
261 AttributeContainerValue<StringValue, ',', std::vector> ac(ref);
262
263 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
264 auto aciter = ac.Begin();
265 for (auto v : ref)
266 {
267 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
268 NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value");
269 ++aciter;
270 }
271 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
272 }
273
274 {
275 // use int64_t which is default for IntegerValue
276 std::map<std::string, int64_t> ref = {{"one", 1}, {"two", 2}, {"three", 3}};
278
279 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
280 auto aciter = ac.Begin();
281 for (const auto& v : ref)
282 {
283 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
284 bool valCheck =
285 v.first == (*aciter)->Get().first && v.second == (*aciter)->Get().second;
286 NS_TEST_ASSERT_MSG_EQ(valCheck, true, "Incorrect value");
287 ++aciter;
288 }
289 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
290 }
291}
292
293/**
294 * @ingroup attribute-tests
295 *
296 * Attribute serialization and deserialization TestCase.
297 */
299{
300 public:
302
306
307 private:
308 void DoRun() override;
309};
310
312 : TestCase("test serialization and deserialization")
313{
314}
315
316void
318{
319 {
320 // notice embedded spaces
321 std::string doubles = "1.0001, 20.53, -102.3";
322
324 auto checker = MakeAttributeContainerChecker(attr);
325 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
326 acchecker->SetItemChecker(MakeDoubleChecker<double>());
327 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(doubles, checker),
328 true,
329 "Deserialize failed");
330 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 3, "Incorrect container size");
331
332 std::string reserialized = attr.SerializeToString(checker);
333 std::string canonical = doubles;
334 canonical.erase(std::remove(canonical.begin(), canonical.end(), ' '), canonical.end());
335 NS_TEST_ASSERT_MSG_EQ(reserialized, canonical, "Reserialization failed");
336 }
337
338 {
339 // notice embedded spaces
340 std::string ints = "1, 2, -3, -4";
341
343 auto checker = MakeAttributeContainerChecker(attr);
344 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
345 acchecker->SetItemChecker(MakeIntegerChecker<int>());
347 true,
348 "Deserialize failed");
349 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 4, "Incorrect container size");
350
351 std::string reserialized = attr.SerializeToString(checker);
352 std::string canonical = ints;
353 canonical.erase(std::remove(canonical.begin(), canonical.end(), ' '), canonical.end());
354 NS_TEST_ASSERT_MSG_EQ(reserialized, canonical, "Reserialization failed");
355 }
356
357 {
358 std::string strings = "this is a sentence with words";
359
361 auto checker = MakeAttributeContainerChecker(attr);
362 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
363 acchecker->SetItemChecker(MakeStringChecker());
364 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(strings, checker),
365 true,
366 "Deserialize failed");
367 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 6, "Incorrect container size");
368
369 std::string reserialized = attr.SerializeToString(checker);
370 NS_TEST_ASSERT_MSG_EQ(reserialized, strings, "Reserialization failed");
371 }
372
373 {
374 std::string pairs = "one 1,two 2,three 3";
376 auto checker = MakeAttributeContainerChecker(attr);
377 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
378 acchecker->SetItemChecker(
381 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(pairs, checker),
382 true,
383 "Deserialization failed");
384 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 3, "Incorrect container size");
385
386 std::string reserialized = attr.SerializeToString(checker);
387 NS_TEST_ASSERT_MSG_EQ(reserialized, pairs, "Reserialization failed");
388 }
389
390 {
391 std::string tupleVec = "{-1, 2, 3.4};{-2, 1, 4.3}";
393 auto checker = MakeAttributeContainerChecker(attr);
394 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
399 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(tupleVec, checker),
400 true,
401 "Deserialization failed");
402 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 2, "Incorrect container size");
403
404 std::string reserialized = attr.SerializeToString(checker);
405 NS_TEST_ASSERT_MSG_EQ(reserialized, tupleVec, "Reserialization failed");
406 }
407}
408
409/**
410 * @ingroup attribute-tests
411 *
412 * Attribute set and get TestCase.
413 */
415{
416 public:
418
420 {
421 }
422
423 private:
424 void DoRun() override;
425};
426
431
432void
434{
436 {
437 auto doubleList = obj->GetDoubleList();
438 NS_TEST_ASSERT_MSG_EQ(doubleList.empty(), true, "DoubleList initialized incorrectly");
439 }
440
441 const std::list<double> doubles = {1.1, 2.22, 3.333};
442 obj->SetAttribute("DoubleList", AttributeContainerValue<DoubleValue>(doubles));
443 {
444 auto doubleList = obj->GetDoubleList();
445 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.begin(), doubles.end(), doubleList.begin()),
446 true,
447 "DoubleList incorrectly set");
448 }
449
450 obj->ReverseDoubleList();
451 {
452 auto doubleList = obj->GetDoubleList();
453 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.rbegin(), doubles.rend(), doubleList.begin()),
454 true,
455 "DoubleList incorrectly reversed");
456
457 // NOTE: changing the return container here too!
459 obj->GetAttribute("DoubleList", value);
460 NS_TEST_ASSERT_MSG_EQ(doubles.size(), value.GetN(), "AttributeContainerValue wrong size");
461
463 NS_TEST_ASSERT_MSG_EQ(doubles.size(), doublevec.size(), "DoublesVec wrong size");
464 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.rbegin(), doubles.rend(), doublevec.begin()),
465 true,
466 "Incorrect value in doublesvec");
467 }
468
469 const std::vector<int> ints = {-1, 0, 1, 2, 3};
470 // NOTE: here the underlying attribute container type differs from the actual container
471 obj->SetAttribute("IntegerVector", AttributeContainerValue<IntegerValue, ';'>(ints));
472
473 {
474 // NOTE: changing the container here too!
476 obj->GetAttribute("IntegerVector", value);
477 NS_TEST_ASSERT_MSG_EQ(ints.size(), value.GetN(), "AttributeContainerValue wrong size");
478
480 NS_TEST_ASSERT_MSG_EQ(ints.size(), intlist.size(), "Intvec wrong size");
481
482 NS_TEST_ASSERT_MSG_EQ(std::equal(ints.begin(), ints.end(), intlist.begin()),
483 true,
484 "Incorrect value in intvec");
485 }
486
487 std::string intVecPairString("0 1,2,3; 1 0; 2 0,1");
488 // NOTE: here the underlying attribute container type differs from the actual container
489 obj->SetAttribute("IntVecPairVec", StringValue(intVecPairString));
490
491 {
493
494 // NOTE: changing the container here too!
495 AttributeContainerValue<IntVecMapValue, ';'> value;
496 obj->GetAttribute("IntVecPairVec", value);
497 NS_TEST_ASSERT_MSG_EQ(3, value.GetN(), "AttributeContainerValue wrong size"); // 3 pairs
498
500 NS_TEST_ASSERT_MSG_EQ(3, reslist.size(), "IntVecMapValue wrong size");
501 auto reslistIt = reslist.begin();
502 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 0, "Incorrect integer value in first pair");
503 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
504 3,
505 "Incorrect number of integer values in first pair");
506 ++reslistIt;
507 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 1, "Incorrect integer value in second pair");
508 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
509 1,
510 "Incorrect number of integer values in second pair");
511 ++reslistIt;
512 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 2, "Incorrect integer value in third pair");
513 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
514 2,
515 "Incorrect number of integer values in third pair");
516 }
517
518 std::map<std::string, int> map = {{"one", 1}, {"two", 2}, {"three", 3}};
519 obj->SetAttribute("MapStringInt",
521
522 {
524 obj->GetAttribute("MapStringInt", value);
525 NS_TEST_ASSERT_MSG_EQ(map.size(), value.GetN(), "AttributeContainerValue wrong size");
526
527 // could possibly make custom assignment operator to make assignment statement work
528 std::map<std::string, int> mapstrint;
529 auto lst = value.Get();
530 for (const auto& l : lst)
531 {
532 mapstrint[l.first] = l.second;
533 }
534
535 NS_TEST_ASSERT_MSG_EQ(map.size(), mapstrint.size(), "mapstrint wrong size");
536 auto iter = map.begin();
537 for (const auto& v : mapstrint)
538 {
539 bool valCheck = v.first == (*iter).first && v.second == (*iter).second;
540 NS_TEST_ASSERT_MSG_EQ(valCheck, true, "Incorrect value in mapstrint");
541 ++iter;
542 }
543 }
544}
545
546/**
547 * @ingroup attribute-tests
548 *
549 * Attribute attribute container TestCase.
550 */
552{
553 public:
555};
556
564
566 g_attributeContainerTestSuite; //!< Static variable for test initialization
static AttributeContainerTestSuite g_attributeContainerTestSuite
Static variable for test initialization.
uint32_t v
std::vector< int > GetIntVec() const
Get the vector of ints.
std::vector< int > m_intvec
Vector of ints.
void ReverseDoubleList()
Reverses the list of doubles.
std::list< double > m_doublelist
List of doubles.
std::list< double > GetDoubleList() const
Get the list of doubles.
std::map< std::string, int > m_map
Map of <std::string, int>.
static TypeId GetTypeId()
Get the type ID.
void SetIntVec(std::vector< int > vec)
Set the vector of ints to the given vector.
void SetDoubleList(const std::list< double > &doubleList)
Set the list of doubles to the given list.
std::map< int64_t, std::list< int64_t > > m_intVecIntMapping
Mapping integers to vectors.
Attribute serialization and deserialization TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
Test AttributeContainer instantiation, initialization, access.
void DoRun() override
Implementation to actually run this TestCase.
Attribute attribute container TestCase.
A container for one type of attribute.
Iterator End()
NS3-style ending of container.
size_type GetN() const
NS3-style Number of items.
std::string SerializeToString(Ptr< const AttributeChecker > checker) const override
C< item_type > result_type
Type of container returned.
Iterator Begin()
NS3-style beginning of container.
bool DeserializeFromString(std::string value, Ptr< const AttributeChecker > checker) override
Hold a signed integer type.
Definition integer.h:34
Object()
Caller graph was not generated because of its size.
Definition object.cc:93
AttributeValue implementation for Pair.
Definition pair.h:54
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
Hold variables of type string.
Definition string.h:45
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:296
@ QUICK
Fast test.
Definition test.h:1057
TestCase(const TestCase &)=delete
Caller graph was not generated because of its size.
Type
Type of test.
Definition test.h:1271
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:494
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
Ptr< AttributeChecker > MakeAttributeContainerChecker()
Make uninitialized AttributeContainerChecker using explicit types.
Ptr< AttributeChecker > MakeAttributeContainerChecker(const AttributeContainerValue< A, Sep, C > &value)
Make AttributeContainerChecker from AttributeContainerValue.
Ptr< const AttributeAccessor > MakeAttributeContainerAccessor(T1 a1)
Make AttributeContainerAccessor using explicit types.
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
Ptr< const AttributeChecker > MakeIntegerChecker()
Definition integer.h:99
Ptr< AttributeChecker > MakePairChecker(const PairValue< A, B > &value)
Make a PairChecker from a PairValue.
Definition pair.h:272
Ptr< const AttributeChecker > MakeStringChecker()
Definition string.cc:19
Ptr< const AttributeChecker > MakeTupleChecker(Ts... checkers)
Create a TupleChecker from AttributeCheckers associated with TupleValue elements.
Definition tuple.h:532
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#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:133
#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:553
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:605