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 <iterator>
24#include <list>
25#include <map>
26#include <utility>
27#include <vector>
28
29using namespace ns3;
30
31NS_LOG_COMPONENT_DEFINE("AttributeContainerTestSuite");
32
33/**
34 * \file
35 * \ingroup attribute-tests
36 * Attribute container test suite
37 */
38
39/**
40 * \ingroup attribute-tests
41 * Attribute container object.
42 */
44{
45 public:
48
49 /**
50 * Reverses the list of doubles.
51 */
52 void ReverseDoubleList();
53
54 /**
55 * \brief Get the type ID.
56 * \return The object TypeId.
57 */
58 static TypeId GetTypeId();
59
60 /**
61 * Set the list of doubles to the given list
62 *
63 * \param doubleList the given list
64 */
65 void SetDoubleList(const std::list<double>& doubleList);
66 /**
67 * Get the list of doubles
68 *
69 * \return the list of doubles
70 */
71 std::list<double> GetDoubleList() const;
72
73 /**
74 * Set the vector of ints to the given vector
75 *
76 * \param vec the given vector
77 */
78 void SetIntVec(std::vector<int> vec);
79 /**
80 * Get the vector of ints
81 *
82 * \return the vector of ints
83 */
84 std::vector<int> GetIntVec() const;
85
86 private:
87 std::list<double> m_doublelist; //!< List of doubles.
88 std::vector<int> m_intvec; //!< Vector of ints.
89 // TODO(jared): need PairValue attributevalue to handle std::pair elements
90 std::map<std::string, int> m_map; //!< Map of <std::string, int>.
91 std::map<int64_t, std::list<int64_t>> m_intVecIntMapping; //!< Mapping integers to vectors
92};
93
97
101
102TypeId
104{
106
107 static TypeId tid =
108 TypeId("ns3::AttributeContainerObject")
109 .SetParent<Object>()
110 .SetGroupName("Test")
111 .AddConstructor<AttributeContainerObject>()
112 .AddAttribute("DoubleList",
113 "List of doubles",
118 .AddAttribute(
119 "IntegerVector",
120 "Vector of integers",
121 // the container value container differs from the underlying object
123 // the type of the underlying container cannot be deduced
128 .AddAttribute(
129 "MapStringInt",
130 "Map of strings to ints",
131 // the container value container differs from the underlying object
138 .AddAttribute(
139 "IntVecPairVec",
140 "An example of complex attribute that is defined by a vector of pairs consisting "
141 "of an integer value and a vector of integers. In case a string is used to set "
142 "this attribute, the string shall contain the pairs separated by a semicolon (;); "
143 "in every pair, the integer value and the vector of integers are separated by a "
144 "blank space, and the elements of the vectors are separated by a comma (,) "
145 "without spaces. E.g. \"0 1,2,3; 1 0; 2 0,1\" consists of three pairs containing "
146 "vectors of 3, 1 and 2 elements, respectively.",
147 StringValue(""),
154 return tid;
155}
156
157void
162
163void
164AttributeContainerObject::SetDoubleList(const std::list<double>& doubleList)
165{
166 m_doublelist = doubleList;
167}
168
169std::list<double>
174
175void
177{
178 m_intvec = vec;
179}
180
181std::vector<int>
183{
184 return m_intvec;
185}
186
187/**
188 * \ingroup attribute-tests
189 *
190 * Test AttributeContainer instantiation, initialization, access
191 */
193{
194 public:
196
198 {
199 }
200
201 private:
202 void DoRun() override;
203};
204
206 : TestCase("test instantiation, initialization, access")
207{
208}
209
210void
212{
213 {
214 std::list<double> ref = {1.0, 2.1, 3.145269};
215
217
218 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
219 auto aciter = ac.Begin();
220 for (auto rend = ref.end(), riter = ref.begin(); riter != rend; ++riter)
221 {
222 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
223 NS_TEST_ASSERT_MSG_EQ(*riter, (*aciter)->Get(), "Incorrect value");
224 ++aciter;
225 }
226 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
227 }
228
229 {
230 std::vector<int> ref = {-2, 3, 10, -1042};
231
232 AttributeContainerValue<IntegerValue> ac(ref.begin(), ref.end());
233
234 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
235 auto aciter = ac.Begin();
236 for (auto rend = ref.end(), riter = ref.begin(); riter != rend; ++riter)
237 {
238 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
239 NS_TEST_ASSERT_MSG_EQ(*riter, (*aciter)->Get(), "Incorrect value");
240 ++aciter;
241 }
242 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
243 }
244
245 {
246 auto ref = {"one", "two", "three"};
247 AttributeContainerValue<StringValue> ac(ref.begin(), ref.end());
248
249 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
250 auto aciter = ac.Begin();
251 for (auto v : ref)
252 {
253 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
254 NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value");
255 ++aciter;
256 }
257 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
258 }
259
260 {
261 auto ref = {"one", "two", "three"};
262 AttributeContainerValue<StringValue, ',', std::vector> ac(ref);
263
264 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
265 auto aciter = ac.Begin();
266 for (auto v : ref)
267 {
268 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
269 NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value");
270 ++aciter;
271 }
272 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
273 }
274
275 {
276 // use int64_t which is default for IntegerValue
277 std::map<std::string, int64_t> ref = {{"one", 1}, {"two", 2}, {"three", 3}};
279
280 NS_TEST_ASSERT_MSG_EQ(ref.size(), ac.GetN(), "Container size mismatch");
281 auto aciter = ac.Begin();
282 for (const auto& v : ref)
283 {
284 NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end");
285 bool valCheck =
286 v.first == (*aciter)->Get().first && v.second == (*aciter)->Get().second;
287 NS_TEST_ASSERT_MSG_EQ(valCheck, true, "Incorrect value");
288 ++aciter;
289 }
290 NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end");
291 }
292}
293
294/**
295 * \ingroup attribute-tests
296 *
297 * Attribute serialization and deserialization TestCase.
298 */
300{
301 public:
303
307
308 private:
309 void DoRun() override;
310};
311
313 : TestCase("test serialization and deserialization")
314{
315}
316
317void
319{
320 {
321 // notice embedded spaces
322 std::string doubles = "1.0001, 20.53, -102.3";
323
325 auto checker = MakeAttributeContainerChecker(attr);
326 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
327 acchecker->SetItemChecker(MakeDoubleChecker<double>());
328 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(doubles, checker),
329 true,
330 "Deserialize failed");
331 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 3, "Incorrect container size");
332
333 std::string reserialized = attr.SerializeToString(checker);
334 std::string canonical = doubles;
335 canonical.erase(std::remove(canonical.begin(), canonical.end(), ' '), canonical.end());
336 NS_TEST_ASSERT_MSG_EQ(reserialized, canonical, "Reserialization failed");
337 }
338
339 {
340 // notice embedded spaces
341 std::string ints = "1, 2, -3, -4";
342
344 auto checker = MakeAttributeContainerChecker(attr);
345 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
346 acchecker->SetItemChecker(MakeIntegerChecker<int>());
348 true,
349 "Deserialize failed");
350 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 4, "Incorrect container size");
351
352 std::string reserialized = attr.SerializeToString(checker);
353 std::string canonical = ints;
354 canonical.erase(std::remove(canonical.begin(), canonical.end(), ' '), canonical.end());
355 NS_TEST_ASSERT_MSG_EQ(reserialized, canonical, "Reserialization failed");
356 }
357
358 {
359 std::string strings = "this is a sentence with words";
360
362 auto checker = MakeAttributeContainerChecker(attr);
363 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
364 acchecker->SetItemChecker(MakeStringChecker());
365 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(strings, checker),
366 true,
367 "Deserialize failed");
368 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 6, "Incorrect container size");
369
370 std::string reserialized = attr.SerializeToString(checker);
371 NS_TEST_ASSERT_MSG_EQ(reserialized, strings, "Reserialization failed");
372 }
373
374 {
375 std::string pairs = "one 1,two 2,three 3";
377 auto checker = MakeAttributeContainerChecker(attr);
378 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
379 acchecker->SetItemChecker(
382 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(pairs, checker),
383 true,
384 "Deserialization failed");
385 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 3, "Incorrect container size");
386
387 std::string reserialized = attr.SerializeToString(checker);
388 NS_TEST_ASSERT_MSG_EQ(reserialized, pairs, "Reserialization failed");
389 }
390
391 {
392 std::string tupleVec = "{-1, 2, 3.4};{-2, 1, 4.3}";
394 auto checker = MakeAttributeContainerChecker(attr);
395 auto acchecker = DynamicCast<AttributeContainerChecker>(checker);
400 NS_TEST_ASSERT_MSG_EQ(attr.DeserializeFromString(tupleVec, checker),
401 true,
402 "Deserialization failed");
403 NS_TEST_ASSERT_MSG_EQ(attr.GetN(), 2, "Incorrect container size");
404
405 std::string reserialized = attr.SerializeToString(checker);
406 NS_TEST_ASSERT_MSG_EQ(reserialized, tupleVec, "Reserialization failed");
407 }
408}
409
410/**
411 * \ingroup attribute-tests
412 *
413 * Attribute set and get TestCase.
414 */
416{
417 public:
419
421 {
422 }
423
424 private:
425 void DoRun() override;
426};
427
432
433void
435{
437 {
438 auto doubleList = obj->GetDoubleList();
439 NS_TEST_ASSERT_MSG_EQ(doubleList.empty(), true, "DoubleList initialized incorrectly");
440 }
441
442 const std::list<double> doubles = {1.1, 2.22, 3.333};
443 obj->SetAttribute("DoubleList", AttributeContainerValue<DoubleValue>(doubles));
444 {
445 auto doubleList = obj->GetDoubleList();
446 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.begin(), doubles.end(), doubleList.begin()),
447 true,
448 "DoubleList incorrectly set");
449 }
450
451 obj->ReverseDoubleList();
452 {
453 auto doubleList = obj->GetDoubleList();
454 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.rbegin(), doubles.rend(), doubleList.begin()),
455 true,
456 "DoubleList incorrectly reversed");
457
458 // NOTE: changing the return container here too!
460 obj->GetAttribute("DoubleList", value);
461 NS_TEST_ASSERT_MSG_EQ(doubles.size(), value.GetN(), "AttributeContainerValue wrong size");
462
464 NS_TEST_ASSERT_MSG_EQ(doubles.size(), doublevec.size(), "DoublesVec wrong size");
465 NS_TEST_ASSERT_MSG_EQ(std::equal(doubles.rbegin(), doubles.rend(), doublevec.begin()),
466 true,
467 "Incorrect value in doublesvec");
468 }
469
470 const std::vector<int> ints = {-1, 0, 1, 2, 3};
471 // NOTE: here the underlying attribute container type differs from the actual container
472 obj->SetAttribute("IntegerVector", AttributeContainerValue<IntegerValue, ';'>(ints));
473
474 {
475 // NOTE: changing the container here too!
477 obj->GetAttribute("IntegerVector", value);
478 NS_TEST_ASSERT_MSG_EQ(ints.size(), value.GetN(), "AttributeContainerValue wrong size");
479
481 NS_TEST_ASSERT_MSG_EQ(ints.size(), intlist.size(), "Intvec wrong size");
482
483 NS_TEST_ASSERT_MSG_EQ(std::equal(ints.begin(), ints.end(), intlist.begin()),
484 true,
485 "Incorrect value in intvec");
486 }
487
488 std::string intVecPairString("0 1,2,3; 1 0; 2 0,1");
489 // NOTE: here the underlying attribute container type differs from the actual container
490 obj->SetAttribute("IntVecPairVec", StringValue(intVecPairString));
491
492 {
494
495 // NOTE: changing the container here too!
496 AttributeContainerValue<IntVecMapValue, ';'> value;
497 obj->GetAttribute("IntVecPairVec", value);
498 NS_TEST_ASSERT_MSG_EQ(3, value.GetN(), "AttributeContainerValue wrong size"); // 3 pairs
499
501 NS_TEST_ASSERT_MSG_EQ(3, reslist.size(), "IntVecMapValue wrong size");
502 auto reslistIt = reslist.begin();
503 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 0, "Incorrect integer value in first pair");
504 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
505 3,
506 "Incorrect number of integer values in first pair");
507 ++reslistIt;
508 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 1, "Incorrect integer value in second pair");
509 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
510 1,
511 "Incorrect number of integer values in second pair");
512 ++reslistIt;
513 NS_TEST_ASSERT_MSG_EQ(reslistIt->first, 2, "Incorrect integer value in third pair");
514 NS_TEST_ASSERT_MSG_EQ(reslistIt->second.size(),
515 2,
516 "Incorrect number of integer values in third pair");
517 }
518
519 std::map<std::string, int> map = {{"one", 1}, {"two", 2}, {"three", 3}};
520 obj->SetAttribute("MapStringInt",
522
523 {
525 obj->GetAttribute("MapStringInt", value);
526 NS_TEST_ASSERT_MSG_EQ(map.size(), value.GetN(), "AttributeContainerValue wrong size");
527
528 // could possibly make custom assignment operator to make assignment statement work
529 std::map<std::string, int> mapstrint;
530 auto lst = value.Get();
531 for (const auto& l : lst)
532 {
533 mapstrint[l.first] = l.second;
534 }
535
536 NS_TEST_ASSERT_MSG_EQ(map.size(), mapstrint.size(), "mapstrint wrong size");
537 auto iter = map.begin();
538 for (const auto& v : mapstrint)
539 {
540 bool valCheck = v.first == (*iter).first && v.second == (*iter).second;
541 NS_TEST_ASSERT_MSG_EQ(valCheck, true, "Incorrect value in mapstrint");
542 ++iter;
543 }
544 }
545}
546
547/**
548 * \ingroup attribute-tests
549 *
550 * Attribute attribute container TestCase.
551 */
553{
554 public:
556};
557
559 : TestSuite("attribute-container-test-suite", Type::UNIT)
560{
561 AddTestCase(new AttributeContainerTestCase(), TestCase::Duration::QUICK);
562 AddTestCase(new AttributeContainerSerializationTestCase(), TestCase::Duration::QUICK);
563 AddTestCase(new AttributeContainerSetGetTestCase(), TestCase::Duration::QUICK);
564}
565
567 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.
bool DeserializeFromString(std::string value, Ptr< const AttributeChecker > checker) override
Hold a signed integer type.
Definition integer.h:34
A base class which provides memory management and object aggregation.
Definition object.h:78
AttributeValue implementation for Pair.
Definition pair.h:54
Smart pointer class similar to boost::intrusive_ptr.
Hold variables of type string.
Definition string.h:45
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
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Ptr< AttributeChecker > MakeAttributeContainerChecker()
Make uninitialized AttributeContainerChecker using explicit types.
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()
Make a PairChecker without abscissa and ordinate AttributeCheckers.
Definition pair.h:289
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:529
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:191
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#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
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:580