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
53{
54 public:
57
61 void ReverseDoubleList();
62
67 static TypeId GetTypeId();
68
74 void SetDoubleList(const std::list<double>& doubleList);
80 std::list<double> GetDoubleList() const;
81
87 void SetIntVec(std::vector<int> vec);
93 std::vector<int> GetIntVec() const;
94
95 private:
96 std::list<double> m_doublelist;
97 std::vector<int> m_intvec;
98 // TODO(jared): need PairValue attributevalue to handle std::pair elements
99 std::map<std::string, int> m_map;
100 std::map<int64_t, std::list<int64_t>> m_intVecIntMapping;
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
205template <class A, class B, class C, class D>
206bool
207operator==(const std::pair<A, B>& x, const std::pair<C, D>& y)
208{
209 return x.first == y.first && x.second == y.second;
210}
211
218{
219 public:
221
223 {
224 }
225
226 private:
227 void DoRun() override;
228};
229
231 : TestCase("test instantiation, initialization, access")
232{
233}
234
235void
237{
238 {
239 std::list<double> ref = {1.0, 2.1, 3.145269};
240
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 std::vector<int> ref = {-2, 3, 10, -1042};
256
257 AttributeContainerValue<IntegerValue> ac(ref.begin(), ref.end());
258
259 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
260 auto aciter = ac.Begin();
261 for (auto rend = ref.end(), riter = ref.begin(); riter != rend; ++riter)
262 {
263 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
264 NS_TEST_ASSERT_MSG_EQ(*riter, (*aciter)->Get(), "Incorrect value");
265 ++aciter;
266 }
267 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
268 }
269
270 {
271 auto ref = {"one", "two", "three"};
272 AttributeContainerValue<StringValue> ac(ref.begin(), ref.end());
273
274 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
275 auto aciter = ac.Begin();
276 for (auto v : ref)
277 {
278 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
279 NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value");
280 ++aciter;
281 }
282 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
283 }
284
285 {
286 auto ref = {"one", "two", "three"};
287 AttributeContainerValue<StringValue, ',', std::vector> ac(ref);
288
289 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
290 auto aciter = ac.Begin();
291 for (auto v : ref)
292 {
293 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
294 NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value");
295 ++aciter;
296 }
297 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
298 }
299
300 {
301 // use int64_t which is default for IntegerValue
302 std::map<std::string, int64_t> ref = {{"one", 1}, {"two", 2}, {"three", 3}};
304
305 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
306 auto aciter = ac.Begin();
307 for (const auto& v : ref)
308 {
309 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
310 NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value");
311 ++aciter;
312 }
313 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
314 }
315}
316
323{
324 public:
326
328 {
329 }
330
331 private:
332 void DoRun() override;
333};
334
336 : TestCase("test serialization and deserialization")
337{
338}
339
340void
342{
343 {
344 // notice embedded spaces
345 std::string doubles = "1.0001, 20.53, -102.3";
346
348 auto checker = MakeAttributeContainerChecker(attr);
349 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
350 acchecker->SetItemChecker(MakeDoubleChecker<double>());
351 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(doubles, checker),
352 true,
353 "Deserialize failed");
354 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 3, "Incorrect container size");
355
356 std::string reserialized = attr.SerializeToString(checker);
357 std::string canonical = doubles;
358 canonical.erase(std::remove(canonical.begin(), canonical.end(), ' '), canonical.end());
359 NS_TEST_ASSERT_MSG_EQ(reserialized, canonical, "Reserialization failed");
360 }
361
362 {
363 // notice embedded spaces
364 std::string ints = "1, 2, -3, -4";
365
367 auto checker = MakeAttributeContainerChecker(attr);
368 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
369 acchecker->SetItemChecker(MakeIntegerChecker<int>());
371 true,
372 "Deserialize failed");
373 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 4, "Incorrect container size");
374
375 std::string reserialized = attr.SerializeToString(checker);
376 std::string canonical = ints;
377 canonical.erase(std::remove(canonical.begin(), canonical.end(), ' '), canonical.end());
378 NS_TEST_ASSERT_MSG_EQ(reserialized, canonical, "Reserialization failed");
379 }
380
381 {
382 std::string strings = "this is a sentence with words";
383
385 auto checker = MakeAttributeContainerChecker(attr);
386 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
387 acchecker->SetItemChecker(MakeStringChecker());
388 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(strings, checker),
389 true,
390 "Deserialize failed");
391 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 6, "Incorrect container size");
392
393 std::string reserialized = attr.SerializeToString(checker);
394 NS_TEST_ASSERT_MSG_EQ(reserialized, strings, "Reserialization failed");
395 }
396
397 {
398 std::string pairs = "one 1,two 2,three 3";
400 auto checker = MakeAttributeContainerChecker(attr);
401 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
402 acchecker->SetItemChecker(
403 MakePairChecker<StringValue, IntegerValue>(MakeStringChecker(),
404 MakeIntegerChecker<int>()));
405 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(pairs, checker),
406 true,
407 "Deserialization failed");
408 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 3, "Incorrect container size");
409
410 std::string reserialized = attr.SerializeToString(checker);
411 NS_TEST_ASSERT_MSG_EQ(reserialized, pairs, "Reserealization failed");
412 }
413}
414
421{
422 public:
424
426 {
427 }
428
429 private:
430 void DoRun() override;
431};
432
434 : TestCase("test attribute set and get")
435{
436}
437
438void
440{
441 Ptr<AttributeContainerObject> obj = CreateObject<AttributeContainerObject>();
442 {
443 auto doubleList = obj->GetDoubleList();
444 NS_TEST_ASSERT_MSG_EQ(doubleList.empty(), true, "DoubleList initialized incorrectly");
445 }
446
447 const std::list<double> doubles = {1.1, 2.22, 3.333};
448 obj->SetAttribute("DoubleList", AttributeContainerValue<DoubleValue>(doubles));
449 {
450 auto doubleList = obj->GetDoubleList();
451 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.begin(), doubles.end(), doubleList.begin()),
452 true,
453 "DoubleList incorrectly set");
454 }
455
456 obj->ReverseDoubleList();
457 {
458 auto doubleList = obj->GetDoubleList();
459 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.rbegin(), doubles.rend(), doubleList.begin()),
460 true,
461 "DoubleList incorrectly reversed");
462
463 // NOTE: changing the return container here too!
465 obj->GetAttribute("DoubleList", value);
466 NS_TEST_ASSERT_MSG_EQ(doubles.size(), value.GetN(), "AttributeContainerValue wrong size");
467
469 NS_TEST_ASSERT_MSG_EQ(doubles.size(), doublevec.size(), "DoublesVec wrong size");
470 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.rbegin(), doubles.rend(), doublevec.begin()),
471 true,
472 "Incorrect value in doublesvec");
473 }
474
475 const std::vector<int> ints = {-1, 0, 1, 2, 3};
476 // NOTE: here the underlying attribute container type differs from the actual container
477 obj->SetAttribute("IntegerVector", AttributeContainerValue<IntegerValue, ';'>(ints));
478
479 {
480 // NOTE: changing the container here too!
482 obj->GetAttribute("IntegerVector", value);
483 NS_TEST_ASSERT_MSG_EQ(ints.size(), value.GetN(), "AttributeContainerValue wrong size");
484
486 NS_TEST_ASSERT_MSG_EQ(ints.size(), intlist.size(), "Intvec wrong size");
487
488 NS_TEST_ASSERT_MSG_EQ(std::equal(ints.begin(), ints.end(), intlist.begin()),
489 true,
490 "Incorrect value in intvec");
491 }
492
493 std::string intVecPairString("0 1,2,3; 1 0; 2 0,1");
494 // NOTE: here the underlying attribute container type differs from the actual container
495 obj->SetAttribute("IntVecPairVec", StringValue(intVecPairString));
496
497 {
499
500 // NOTE: changing the container here too!
501 AttributeContainerValue<IntVecMapValue, ';'> value;
502 obj->GetAttribute("IntVecPairVec", value);
503 NS_TEST_ASSERT_MSG_EQ(3, value.GetN(), "AttributeContainerValue wrong size"); // 3 pairs
504
506 NS_TEST_ASSERT_MSG_EQ(3, reslist.size(), "IntVecMapValue wrong size");
507 auto reslistIt = reslist.begin();
508 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 0, "Incorrect integer value in first pair");
509 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
510 3,
511 "Incorrect number of integer values in first pair");
512 ++reslistIt;
513 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 1, "Incorrect integer value in second pair");
514 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
515 1,
516 "Incorrect number of integer values in second pair");
517 ++reslistIt;
518 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 2, "Incorrect integer value in third pair");
519 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
520 2,
521 "Incorrect number of integer values in third pair");
522 }
523
524 std::map<std::string, int> map = {{"one", 1}, {"two", 2}, {"three", 3}};
525 obj->SetAttribute("MapStringInt",
527
528 {
530 obj->GetAttribute("MapStringInt", value);
531 NS_TEST_ASSERT_MSG_EQ(map.size(), value.GetN(), "AttributeContainerValue wrong size");
532
533 // could possibly make custom assignment operator to make assignment statement work
534 std::map<std::string, int> mapstrint;
535 auto lst = value.Get();
536 for (const auto& l : lst)
537 {
538 mapstrint[l.first] = l.second;
539 }
540
541 NS_TEST_ASSERT_MSG_EQ(map.size(), mapstrint.size(), "mapstrint wrong size");
542 auto iter = map.begin();
543 for (const auto& v : mapstrint)
544 {
545 NS_TEST_ASSERT_MSG_EQ(v, *iter, "Incorrect value in mapstrint");
546 ++iter;
547 }
548 }
549}
550
557{
558 public:
560};
561
563 : TestSuite("attribute-container-test-suite", UNIT)
564{
568}
569
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
Hold objects of type std::pair<A, B>.
Definition: pair.h:56
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
@ QUICK
Fast test.
Definition: test.h:1065
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
bool operator==(const std::pair< A, B > &x, const std::pair< C, D > &y)
This function handles mixed constness and compatible, yet distinct numerical classes (like int and lo...
Ptr< AttributeChecker > MakePairChecker()
Make a PairChecker without abscissa and ordinate AttributeCheckers.
Definition: pair.h:253
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:144
#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:564
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< AttributeChecker > MakeAttributeContainerChecker()
Make uninitialized AttributeContainerChecker using explicit types.