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 * 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: Jared Dulmage <jared.dulmage@caliola.com>
18 */
19
20#include <ns3/attribute-container.h>
21#include <ns3/double.h>
22#include <ns3/integer.h>
23#include <ns3/log.h>
24#include <ns3/object.h>
25#include <ns3/pair.h>
26#include <ns3/ptr.h>
27#include <ns3/string.h>
28#include <ns3/test.h>
29#include <ns3/type-id.h>
30
31#include <algorithm>
32#include <iterator>
33#include <list>
34#include <map>
35#include <utility>
36#include <vector>
37
38using namespace ns3;
39
40NS_LOG_COMPONENT_DEFINE("AttributeContainerTestSuite");
41
42/**
43 * \file
44 * \ingroup attribute-tests
45 * Attribute container test suite
46 */
47
48/**
49 * \ingroup attribute-tests
50 * Attribute container object.
51 */
53{
54 public:
57
58 /**
59 * Reverses the list of doubles.
60 */
61 void ReverseDoubleList();
62
63 /**
64 * \brief Get the type ID.
65 * \return The object TypeId.
66 */
67 static TypeId GetTypeId();
68
69 /**
70 * Set the list of doubles to the given list
71 *
72 * \param doubleList the given list
73 */
74 void SetDoubleList(const std::list<double>& doubleList);
75 /**
76 * Get the list of doubles
77 *
78 * \return the list of doubles
79 */
80 std::list<double> GetDoubleList() const;
81
82 /**
83 * Set the vector of ints to the given vector
84 *
85 * \param vec the given vector
86 */
87 void SetIntVec(std::vector<int> vec);
88 /**
89 * Get the vector of ints
90 *
91 * \return the vector of ints
92 */
93 std::vector<int> GetIntVec() const;
94
95 private:
96 std::list<double> m_doublelist; //!< List of doubles.
97 std::vector<int> m_intvec; //!< Vector of ints.
98 // TODO(jared): need PairValue attributevalue to handle std::pair elements
99 std::map<std::string, int> m_map; //!< Map of <std::string, int>.
100 std::map<int64_t, std::list<int64_t>> m_intVecIntMapping; //!< Mapping integers to vectors
101};
102
104{
105}
106
108{
109}
110
111TypeId
113{
115
116 static TypeId tid =
117 TypeId("ns3::AttributeContainerObject")
118 .SetParent<Object>()
119 .SetGroupName("Test")
120 .AddConstructor<AttributeContainerObject>()
121 .AddAttribute("DoubleList",
122 "List of doubles",
124 MakeAttributeContainerAccessor<DoubleValue>(
126 MakeAttributeContainerChecker<DoubleValue>(MakeDoubleChecker<double>()))
127 .AddAttribute(
128 "IntegerVector",
129 "Vector of integers",
130 // the container value container differs from the underlying object
132 // the type of the underlying container cannot be deduced
133 MakeAttributeContainerAccessor<IntegerValue, ';', std::list>(
136 MakeAttributeContainerChecker<IntegerValue, ';'>(MakeIntegerChecker<int>()))
137 .AddAttribute(
138 "MapStringInt",
139 "Map of strings to ints",
140 // the container value container differs from the underlying object
142 MakeAttributeContainerAccessor<PairValue<StringValue, IntegerValue>>(
145 MakePairChecker<StringValue, IntegerValue>(MakeStringChecker(),
146 MakeIntegerChecker<int>())))
147 .AddAttribute(
148 "IntVecPairVec",
149 "An example of complex attribute that is defined by a vector of pairs consisting "
150 "of an integer value and a vector of integers. In case a string is used to set "
151 "this attribute, the string shall contain the pairs separated by a semicolon (;); "
152 "in every pair, the integer value and the vector of integers are separated by a "
153 "blank space, and the elements of the vectors are separated by a comma (,) "
154 "without spaces. E.g. \"0 1,2,3; 1 0; 2 0,1\" consists of three pairs containing "
155 "vectors of 3, 1 and 2 elements, respectively.",
156 StringValue(""),
157 MakeAttributeContainerAccessor<IntVecMapValue, ';'>(
159 MakeAttributeContainerChecker<IntVecMapValue, ';'>(
161 MakeIntegerChecker<int>(),
162 MakeAttributeContainerChecker<IntegerValue>(MakeIntegerChecker<int>()))));
163 return tid;
164}
165
166void
168{
169 m_doublelist.reverse();
170}
171
172void
173AttributeContainerObject::SetDoubleList(const std::list<double>& doubleList)
174{
175 m_doublelist = doubleList;
176}
177
178std::list<double>
180{
181 return m_doublelist;
182}
183
184void
186{
187 m_intvec = vec;
188}
189
190std::vector<int>
192{
193 return m_intvec;
194}
195
196/**
197 * \ingroup attribute-tests
198 *
199 * Test AttributeContainer instantiation, initialization, access
200 */
202{
203 public:
205
207 {
208 }
209
210 private:
211 void DoRun() override;
212};
213
215 : TestCase("test instantiation, initialization, access")
216{
217}
218
219void
221{
222 {
223 std::list<double> ref = {1.0, 2.1, 3.145269};
224
226
227 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
228 auto aciter = ac.Begin();
229 for (auto rend = ref.end(), riter = ref.begin(); riter != rend; ++riter)
230 {
231 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
232 NS_TEST_ASSERT_MSG_EQ(*riter, (*aciter)->Get(), "Incorrect value");
233 ++aciter;
234 }
235 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
236 }
237
238 {
239 std::vector<int> ref = {-2, 3, 10, -1042};
240
241 AttributeContainerValue<IntegerValue> ac(ref.begin(), ref.end());
242
243 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
244 auto aciter = ac.Begin();
245 for (auto rend = ref.end(), riter = ref.begin(); riter != rend; ++riter)
246 {
247 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
248 NS_TEST_ASSERT_MSG_EQ(*riter, (*aciter)->Get(), "Incorrect value");
249 ++aciter;
250 }
251 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
252 }
253
254 {
255 auto ref = {"one", "two", "three"};
256 AttributeContainerValue<StringValue> ac(ref.begin(), ref.end());
257
258 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
259 auto aciter = ac.Begin();
260 for (auto v : ref)
261 {
262 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
263 NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value");
264 ++aciter;
265 }
266 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
267 }
268
269 {
270 auto ref = {"one", "two", "three"};
271 AttributeContainerValue<StringValue, ',', std::vector> ac(ref);
272
273 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
274 auto aciter = ac.Begin();
275 for (auto v : ref)
276 {
277 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
278 NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value");
279 ++aciter;
280 }
281 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
282 }
283
284 {
285 // use int64_t which is default for IntegerValue
286 std::map<std::string, int64_t> ref = {{"one", 1}, {"two", 2}, {"three", 3}};
288
289 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
290 auto aciter = ac.Begin();
291 for (const auto& v : ref)
292 {
293 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
294 bool valCheck =
295 v.first == (*aciter)->Get().first && v.second == (*aciter)->Get().second;
296 NS_TEST_ASSERT_MSG_EQ(valCheck, true, "Incorrect value");
297 ++aciter;
298 }
299 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
300 }
301}
302
303/**
304 * \ingroup attribute-tests
305 *
306 * Attribute serialization and deserialization TestCase.
307 */
309{
310 public:
312
314 {
315 }
316
317 private:
318 void DoRun() override;
319};
320
322 : TestCase("test serialization and deserialization")
323{
324}
325
326void
328{
329 {
330 // notice embedded spaces
331 std::string doubles = "1.0001, 20.53, -102.3";
332
334 auto checker = MakeAttributeContainerChecker(attr);
335 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
336 acchecker->SetItemChecker(MakeDoubleChecker<double>());
337 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(doubles, checker),
338 true,
339 "Deserialize failed");
340 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 3, "Incorrect container size");
341
342 std::string reserialized = attr.SerializeToString(checker);
343 std::string canonical = doubles;
344 canonical.erase(std::remove(canonical.begin(), canonical.end(), ' '), canonical.end());
345 NS_TEST_ASSERT_MSG_EQ(reserialized, canonical, "Reserialization failed");
346 }
347
348 {
349 // notice embedded spaces
350 std::string ints = "1, 2, -3, -4";
351
353 auto checker = MakeAttributeContainerChecker(attr);
354 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
355 acchecker->SetItemChecker(MakeIntegerChecker<int>());
357 true,
358 "Deserialize failed");
359 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 4, "Incorrect container size");
360
361 std::string reserialized = attr.SerializeToString(checker);
362 std::string canonical = ints;
363 canonical.erase(std::remove(canonical.begin(), canonical.end(), ' '), canonical.end());
364 NS_TEST_ASSERT_MSG_EQ(reserialized, canonical, "Reserialization failed");
365 }
366
367 {
368 std::string strings = "this is a sentence with words";
369
371 auto checker = MakeAttributeContainerChecker(attr);
372 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
373 acchecker->SetItemChecker(MakeStringChecker());
374 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(strings, checker),
375 true,
376 "Deserialize failed");
377 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 6, "Incorrect container size");
378
379 std::string reserialized = attr.SerializeToString(checker);
380 NS_TEST_ASSERT_MSG_EQ(reserialized, strings, "Reserialization failed");
381 }
382
383 {
384 std::string pairs = "one 1,two 2,three 3";
386 auto checker = MakeAttributeContainerChecker(attr);
387 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
388 acchecker->SetItemChecker(
389 MakePairChecker<StringValue, IntegerValue>(MakeStringChecker(),
390 MakeIntegerChecker<int>()));
391 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(pairs, checker),
392 true,
393 "Deserialization failed");
394 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 3, "Incorrect container size");
395
396 std::string reserialized = attr.SerializeToString(checker);
397 NS_TEST_ASSERT_MSG_EQ(reserialized, pairs, "Reserealization failed");
398 }
399}
400
401/**
402 * \ingroup attribute-tests
403 *
404 * Attribute set and get TestCase.
405 */
407{
408 public:
410
412 {
413 }
414
415 private:
416 void DoRun() override;
417};
418
420 : TestCase("test attribute set and get")
421{
422}
423
424void
426{
427 Ptr<AttributeContainerObject> obj = CreateObject<AttributeContainerObject>();
428 {
429 auto doubleList = obj->GetDoubleList();
430 NS_TEST_ASSERT_MSG_EQ(doubleList.empty(), true, "DoubleList initialized incorrectly");
431 }
432
433 const std::list<double> doubles = {1.1, 2.22, 3.333};
434 obj->SetAttribute("DoubleList", AttributeContainerValue<DoubleValue>(doubles));
435 {
436 auto doubleList = obj->GetDoubleList();
437 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.begin(), doubles.end(), doubleList.begin()),
438 true,
439 "DoubleList incorrectly set");
440 }
441
442 obj->ReverseDoubleList();
443 {
444 auto doubleList = obj->GetDoubleList();
445 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.rbegin(), doubles.rend(), doubleList.begin()),
446 true,
447 "DoubleList incorrectly reversed");
448
449 // NOTE: changing the return container here too!
451 obj->GetAttribute("DoubleList", value);
452 NS_TEST_ASSERT_MSG_EQ(doubles.size(), value.GetN(), "AttributeContainerValue wrong size");
453
455 NS_TEST_ASSERT_MSG_EQ(doubles.size(), doublevec.size(), "DoublesVec wrong size");
456 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.rbegin(), doubles.rend(), doublevec.begin()),
457 true,
458 "Incorrect value in doublesvec");
459 }
460
461 const std::vector<int> ints = {-1, 0, 1, 2, 3};
462 // NOTE: here the underlying attribute container type differs from the actual container
463 obj->SetAttribute("IntegerVector", AttributeContainerValue<IntegerValue, ';'>(ints));
464
465 {
466 // NOTE: changing the container here too!
468 obj->GetAttribute("IntegerVector", value);
469 NS_TEST_ASSERT_MSG_EQ(ints.size(), value.GetN(), "AttributeContainerValue wrong size");
470
472 NS_TEST_ASSERT_MSG_EQ(ints.size(), intlist.size(), "Intvec wrong size");
473
474 NS_TEST_ASSERT_MSG_EQ(std::equal(ints.begin(), ints.end(), intlist.begin()),
475 true,
476 "Incorrect value in intvec");
477 }
478
479 std::string intVecPairString("0 1,2,3; 1 0; 2 0,1");
480 // NOTE: here the underlying attribute container type differs from the actual container
481 obj->SetAttribute("IntVecPairVec", StringValue(intVecPairString));
482
483 {
485
486 // NOTE: changing the container here too!
487 AttributeContainerValue<IntVecMapValue, ';'> value;
488 obj->GetAttribute("IntVecPairVec", value);
489 NS_TEST_ASSERT_MSG_EQ(3, value.GetN(), "AttributeContainerValue wrong size"); // 3 pairs
490
492 NS_TEST_ASSERT_MSG_EQ(3, reslist.size(), "IntVecMapValue wrong size");
493 auto reslistIt = reslist.begin();
494 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 0, "Incorrect integer value in first pair");
495 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
496 3,
497 "Incorrect number of integer values in first pair");
498 ++reslistIt;
499 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 1, "Incorrect integer value in second pair");
500 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
501 1,
502 "Incorrect number of integer values in second pair");
503 ++reslistIt;
504 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 2, "Incorrect integer value in third pair");
505 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
506 2,
507 "Incorrect number of integer values in third pair");
508 }
509
510 std::map<std::string, int> map = {{"one", 1}, {"two", 2}, {"three", 3}};
511 obj->SetAttribute("MapStringInt",
513
514 {
516 obj->GetAttribute("MapStringInt", value);
517 NS_TEST_ASSERT_MSG_EQ(map.size(), value.GetN(), "AttributeContainerValue wrong size");
518
519 // could possibly make custom assignment operator to make assignment statement work
520 std::map<std::string, int> mapstrint;
521 auto lst = value.Get();
522 for (const auto& l : lst)
523 {
524 mapstrint[l.first] = l.second;
525 }
526
527 NS_TEST_ASSERT_MSG_EQ(map.size(), mapstrint.size(), "mapstrint wrong size");
528 auto iter = map.begin();
529 for (const auto& v : mapstrint)
530 {
531 bool valCheck = v.first == (*iter).first && v.second == (*iter).second;
532 NS_TEST_ASSERT_MSG_EQ(valCheck, true, "Incorrect value in mapstrint");
533 ++iter;
534 }
535 }
536}
537
538/**
539 * \ingroup attribute-tests
540 *
541 * Attribute attribute container TestCase.
542 */
544{
545 public:
547};
548
550 : TestSuite("attribute-container-test-suite", Type::UNIT)
551{
552 AddTestCase(new AttributeContainerTestCase(), TestCase::Duration::QUICK);
553 AddTestCase(new AttributeContainerSerializationTestCase(), TestCase::Duration::QUICK);
554 AddTestCase(new AttributeContainerSetGetTestCase(), TestCase::Duration::QUICK);
555}
556
558 g_attributeContainerTestSuite; //!< Static variable for test initialization
static AttributeContainerTestSuite g_attributeContainerTestSuite
Static variable for test initialization.
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.
size_type size() const
STL-style number of items in container.
iterator begin()
STL-style beginning of container.
bool DeserializeFromString(std::string value, Ptr< const AttributeChecker > checker) override
Hold a signed integer type.
Definition: integer.h:45
A base class which provides memory management and object aggregation.
Definition: object.h:89
AttributeValue implementation for Pair.
Definition: pair.h:65
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Hold variables of type string.
Definition: string.h:56
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
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Ptr< AttributeChecker > MakeAttributeContainerChecker()
Make uninitialized AttributeContainerChecker using explicit types.
Ptr< AttributeChecker > MakePairChecker()
Make a PairChecker without abscissa and ordinate AttributeCheckers.
Definition: pair.h:298
Ptr< const AttributeChecker > MakeStringChecker()
Definition: string.cc:30
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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
Every class exported by the ns3 library is enclosed in the ns3 namespace.