A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
packet-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19#include "ns3/packet-tag-list.h"
20#include "ns3/packet.h"
21#include "ns3/test.h"
22
23#include <cstdarg>
24#include <ctime>
25#include <iomanip>
26#include <iostream>
27#include <limits> // std:numeric_limits
28#include <string>
29
30using namespace ns3;
31
32//-----------------------------------------------------------------------------
33// Unit tests
34//-----------------------------------------------------------------------------
35namespace
36{
37
38/**
39 * \ingroup network-test
40 * \ingroup tests
41 *
42 * \brief Base class for Test tags
43 *
44 * \note Class internal to packet-test-suite.cc
45 */
46class ATestTagBase : public Tag
47{
48 public:
50 : m_error(false),
51 m_data(0)
52 {
53 }
54
55 /// Constructor
56 /// \param data Tag data
58 : m_error(false),
59 m_data(data)
60 {
61 }
62
63 /**
64 * Register this type.
65 * \return The TypeId.
66 */
68 {
69 static TypeId tid =
70 TypeId("ATestTagBase").SetParent<Tag>().SetGroupName("Network").HideFromDocumentation()
71 // No AddConstructor because this is an abstract class.
72 ;
73 return tid;
74 }
75
76 /// Get the tag data.
77 /// \return the tag data.
78 int GetData() const
79 {
80 int result = (int)m_data;
81 return result;
82 }
83
84 bool m_error; //!< Error in the Tag
85 uint8_t m_data; //!< Tag data
86};
87
88/**
89 * \ingroup network-test
90 * \ingroup tests
91 *
92 * \brief Template class for Test tags
93 *
94 * \note Class internal to packet-test-suite.cc
95 */
96template <int N>
97class ATestTag : public ATestTagBase
98{
99 public:
100 /**
101 * Register this type.
102 * \return The TypeId.
103 */
105 {
106 std::ostringstream oss;
107 oss << "anon::ATestTag<" << N << ">";
108 static TypeId tid = TypeId(oss.str())
110 .SetGroupName("Network")
111 .HideFromDocumentation()
112 .AddConstructor<ATestTag<N>>();
113 return tid;
114 }
115
116 TypeId GetInstanceTypeId() const override
117 {
118 return GetTypeId();
119 }
120
122 {
123 return N + sizeof(m_data);
124 }
125
126 void Serialize(TagBuffer buf) const override
127 {
128 buf.WriteU8(m_data);
129 for (uint32_t i = 0; i < N; ++i)
130 {
131 buf.WriteU8(N);
132 }
133 }
134
135 void Deserialize(TagBuffer buf) override
136 {
137 m_data = buf.ReadU8();
138 for (uint32_t i = 0; i < N; ++i)
139 {
140 uint8_t v = buf.ReadU8();
141 if (v != N)
142 {
143 m_error = true;
144 }
145 }
146 }
147
148 void Print(std::ostream& os) const override
149 {
150 os << N << "(" << m_data << ")";
151 }
152
154 : ATestTagBase()
155 {
156 }
157
158 /// Constructor
159 /// \param data Tag data
160 ATestTag(uint8_t data)
162 {
163 }
164};
165
166// Previous versions of ns-3 limited the tag size to 20 bytes or less
167// static const uint8_t LARGE_TAG_BUFFER_SIZE = 64;
168#define LARGE_TAG_BUFFER_SIZE 64
169
170/**
171 * \ingroup network-test
172 * \ingroup tests
173 *
174 * \brief Template class for Large Test tags
175 *
176 * \see Bug 2221: Expanding packet tag maximum size
177 *
178 * \note Class internal to packet-test-suite.cc
179 */
180class ALargeTestTag : public Tag
181{
182 public:
184 {
185 for (uint8_t i = 0; i < (LARGE_TAG_BUFFER_SIZE - 1); i++)
186 {
187 m_data.push_back(i);
188 }
189 m_size = LARGE_TAG_BUFFER_SIZE;
190 }
191
192 /**
193 * Register this type.
194 * \return The TypeId.
195 */
197 {
198 static TypeId tid = TypeId("ALargeTestTag")
199 .SetParent<Tag>()
200 .SetGroupName("Network")
201 .HideFromDocumentation()
202 .AddConstructor<ALargeTestTag>();
203 return tid;
204 }
205
206 TypeId GetInstanceTypeId() const override
207 {
208 return GetTypeId();
209 }
210
212 {
213 return (uint32_t)m_size;
214 }
215
216 void Serialize(TagBuffer buf) const override
217 {
218 buf.WriteU8(m_size);
219 for (uint8_t i = 0; i < (m_size - 1); ++i)
220 {
221 buf.WriteU8(m_data[i]);
222 }
223 }
224
225 void Deserialize(TagBuffer buf) override
226 {
227 m_size = buf.ReadU8();
228 for (uint8_t i = 0; i < (m_size - 1); ++i)
229 {
230 uint8_t v = buf.ReadU8();
231 m_data.push_back(v);
232 }
233 }
234
235 void Print(std::ostream& os) const override
236 {
237 os << "(" << (uint16_t)m_size << ")";
238 }
239
240 private:
241 uint8_t m_size; //!< Packet size
242 std::vector<uint8_t> m_data; //!< Tag data
243};
244
245/**
246 * \ingroup network-test
247 * \ingroup tests
248 *
249 * \brief Base class for Test headers
250 *
251 * \note Class internal to packet-test-suite.cc
252 */
254{
255 public:
257 : Header(),
258 m_error(false)
259 {
260 }
261
262 /**
263 * Register this type.
264 * \return The TypeId.
265 */
267 {
268 static TypeId tid = TypeId("ATestHeaderBase")
269 .SetParent<Header>()
270 .SetGroupName("Network")
271 .HideFromDocumentation()
272 // No AddConstructor because this is an abstract class.
273 ;
274 return tid;
275 }
276
277 bool m_error; //!< Error in the Header
278};
279
280/**
281 * \ingroup network-test
282 * \ingroup tests
283 *
284 * \brief Template class for Test headers
285 *
286 * \note Class internal to packet-test-suite.cc
287 */
288template <int N>
290{
291 public:
292 /**
293 * Register this type.
294 * \return The TypeId.
295 */
297 {
298 std::ostringstream oss;
299 oss << "anon::ATestHeader<" << N << ">";
300 static TypeId tid = TypeId(oss.str())
302 .SetGroupName("Network")
303 .HideFromDocumentation()
304 .AddConstructor<ATestHeader<N>>();
305 return tid;
306 }
307
308 TypeId GetInstanceTypeId() const override
309 {
310 return GetTypeId();
311 }
312
314 {
315 return N;
316 }
317
318 void Serialize(Buffer::Iterator iter) const override
319 {
320 for (uint32_t i = 0; i < N; ++i)
321 {
322 iter.WriteU8(N);
323 }
324 }
325
327 {
328 for (uint32_t i = 0; i < N; ++i)
329 {
330 uint8_t v = iter.ReadU8();
331 if (v != N)
332 {
333 m_error = true;
334 }
335 }
336 return N;
337 }
338
339 void Print(std::ostream& os) const override
340 {
341 }
342
345 {
346 }
347};
348
349/**
350 * \ingroup network-test
351 * \ingroup tests
352 *
353 * \brief Base class for Test trailers
354 *
355 * \note Class internal to packet-test-suite.cc
356 */
358{
359 public:
361 : Trailer(),
362 m_error(false)
363 {
364 }
365
366 /**
367 * Register this type.
368 * \return The TypeId.
369 */
371 {
372 static TypeId tid = TypeId("ATestTrailerBase")
374 .SetGroupName("Network")
375 .HideFromDocumentation()
376 // No AddConstructor because this is an abstract class.
377 ;
378 return tid;
379 }
380
381 bool m_error; //!< Error in the Trailer
382};
383
384/**
385 * \ingroup network-test
386 * \ingroup tests
387 *
388 * \brief Template class for Test trailers
389 *
390 * \note Class internal to packet-test-suite.cc
391 */
392template <int N>
394{
395 public:
396 /**
397 * Register this type.
398 * \return The TypeId.
399 */
401 {
402 std::ostringstream oss;
403 oss << "anon::ATestTrailer<" << N << ">";
404 static TypeId tid = TypeId(oss.str())
406 .SetGroupName("Network")
407 .HideFromDocumentation()
408 .AddConstructor<ATestTrailer<N>>();
409 return tid;
410 }
411
412 TypeId GetInstanceTypeId() const override
413 {
414 return GetTypeId();
415 }
416
418 {
419 return N;
420 }
421
422 void Serialize(Buffer::Iterator iter) const override
423 {
424 iter.Prev(N);
425 for (uint32_t i = 0; i < N; ++i)
426 {
427 iter.WriteU8(N);
428 }
429 }
430
432 {
433 iter.Prev(N);
434 for (uint32_t i = 0; i < N; ++i)
435 {
436 uint8_t v = iter.ReadU8();
437 if (v != N)
438 {
439 m_error = true;
440 }
441 }
442 return N;
443 }
444
445 void Print(std::ostream& os) const override
446 {
447 }
448
451 {
452 }
453};
454
455/**
456 * \ingroup network-test
457 * \ingroup tests
458 *
459 * \brief Struct to hold the expected data in the packet
460 *
461 * \note Class internal to packet-test-suite.cc
462 */
464{
465 /**
466 * Constructor
467 * \param n_ Number of elements
468 * \param start_ Start
469 * \param end_ End
470 */
472 : n(n_),
473 start(start_),
474 end(end_),
475 data(0)
476 {
477 }
478
479 /**
480 * Constructor
481 * \param n_ Number of elements
482 * \param start_ Start
483 * \param end_ End
484 * \param data_ Data stored in tag
485 */
486 Expected(uint32_t n_, uint32_t start_, uint32_t end_, uint8_t data_)
487 : n(n_),
488 start(start_),
489 end(end_),
490 data(data_)
491 {
492 }
493
494 uint32_t n; //!< Number of elements
495 uint32_t start; //!< Start
496 uint32_t end; //!< End
497 uint8_t data; //!< Optional data
498};
499
500} // namespace
501
502// tag name, start, end
503#define E(name, start, end) name, start, end
504
505// tag name, start, end, data
506#define E_DATA(name, start, end, data) name, start, end, data
507
508// Check byte tags on a packet, checks name, start, end
509#define CHECK(p, n, ...) DoCheck(p, n, __VA_ARGS__)
510
511// Check byte tags on a packet, checks name, start, end, data
512#define CHECK_DATA(p, n, ...) DoCheckData(p, n, __VA_ARGS__)
513
514/**
515 * \ingroup network-test
516 * \ingroup tests
517 *
518 * Packet unit tests.
519 */
520class PacketTest : public TestCase
521{
522 public:
523 PacketTest();
524 void DoRun() override;
525
526 private:
527 /**
528 * Checks the packet
529 * \param p The packet
530 * \param n The number of variable arguments
531 * \param ... The variable arguments
532 */
533 void DoCheck(Ptr<const Packet> p, uint32_t n, ...);
534 /**
535 * Checks the packet and its data
536 * \param p The packet
537 * \param n The number of variable arguments
538 * \param ... The variable arguments
539 */
540 void DoCheckData(Ptr<const Packet> p, uint32_t n, ...);
541};
542
544 : TestCase("Packet")
545{
546}
547
548void
550{
551 std::vector<Expected> expected;
552 va_list ap;
553 va_start(ap, n);
554 for (uint32_t k = 0; k < n; ++k)
555 {
556 uint32_t N = va_arg(ap, uint32_t);
557 uint32_t start = va_arg(ap, uint32_t);
558 uint32_t end = va_arg(ap, uint32_t);
559 expected.emplace_back(N, start, end);
560 }
561 va_end(ap);
562
563 ByteTagIterator i = p->GetByteTagIterator();
564 uint32_t j = 0;
565 while (i.HasNext() && j < expected.size())
566 {
567 ByteTagIterator::Item item = i.Next();
568 Expected e = expected[j];
569 std::ostringstream oss;
570 oss << "anon::ATestTag<" << e.n << ">";
571 NS_TEST_EXPECT_MSG_EQ(item.GetTypeId().GetName(), oss.str(), "trivial");
572 NS_TEST_EXPECT_MSG_EQ(item.GetStart(), e.start, "trivial");
573 NS_TEST_EXPECT_MSG_EQ(item.GetEnd(), e.end, "trivial");
574 ATestTagBase* tag = dynamic_cast<ATestTagBase*>(item.GetTypeId().GetConstructor()());
575 NS_TEST_EXPECT_MSG_NE(tag, 0, "trivial");
576 item.GetTag(*tag);
577 NS_TEST_EXPECT_MSG_EQ(tag->m_error, false, "trivial");
578 delete tag;
579 j++;
580 }
581 NS_TEST_EXPECT_MSG_EQ(i.HasNext(), false, "Nothing left");
582 NS_TEST_EXPECT_MSG_EQ(j, expected.size(), "Size match");
583}
584
585void
587{
588 std::vector<Expected> expected;
589 va_list ap;
590 va_start(ap, n);
591 for (uint32_t k = 0; k < n; ++k)
592 {
593 uint32_t N = va_arg(ap, uint32_t);
594 uint32_t start = va_arg(ap, uint32_t);
595 uint32_t end = va_arg(ap, uint32_t);
596 int data = va_arg(ap, int);
597 expected.emplace_back(N, start, end, data);
598 }
599 va_end(ap);
600
601 ByteTagIterator i = p->GetByteTagIterator();
602 uint32_t j = 0;
603 while (i.HasNext() && j < expected.size())
604 {
605 ByteTagIterator::Item item = i.Next();
606 Expected e = expected[j];
607 std::ostringstream oss;
608 oss << "anon::ATestTag<" << e.n << ">";
609 NS_TEST_EXPECT_MSG_EQ(item.GetTypeId().GetName(), oss.str(), "trivial");
610 NS_TEST_EXPECT_MSG_EQ(item.GetStart(), e.start, "trivial");
611 NS_TEST_EXPECT_MSG_EQ(item.GetEnd(), e.end, "trivial");
612 ATestTagBase* tag = dynamic_cast<ATestTagBase*>(item.GetTypeId().GetConstructor()());
613 NS_TEST_EXPECT_MSG_NE(tag, 0, "trivial");
614 item.GetTag(*tag);
615 NS_TEST_EXPECT_MSG_EQ(tag->m_error, false, "trivial");
616 NS_TEST_EXPECT_MSG_EQ(tag->GetData(), e.data, "trivial");
617 delete tag;
618 j++;
619 }
620 NS_TEST_EXPECT_MSG_EQ(i.HasNext(), false, "Nothing left");
621 NS_TEST_EXPECT_MSG_EQ(j, expected.size(), "Size match");
622}
623
624void
626{
627 Ptr<Packet> pkt1 = Create<Packet>(reinterpret_cast<const uint8_t*>("hello"), 5);
628 Ptr<Packet> pkt2 = Create<Packet>(reinterpret_cast<const uint8_t*>(" world"), 6);
629 Ptr<Packet> packet = Create<Packet>();
630 packet->AddAtEnd(pkt1);
631 packet->AddAtEnd(pkt2);
632
633 NS_TEST_EXPECT_MSG_EQ(packet->GetSize(), 11, "trivial");
634
635 auto buf = new uint8_t[packet->GetSize()];
636 packet->CopyData(buf, packet->GetSize());
637
638 std::string msg = std::string(reinterpret_cast<const char*>(buf), packet->GetSize());
639 delete[] buf;
640
641 NS_TEST_EXPECT_MSG_EQ(msg, "hello world", "trivial");
642
643 Ptr<const Packet> p = Create<Packet>(1000);
644
645 p->AddByteTag(ATestTag<1>());
646 CHECK(p, 1, E(1, 0, 1000));
647 Ptr<const Packet> copy = p->Copy();
648 CHECK(copy, 1, E(1, 0, 1000));
649
650 p->AddByteTag(ATestTag<2>());
651 CHECK(p, 2, E(1, 0, 1000), E(2, 0, 1000));
652 CHECK(copy, 1, E(1, 0, 1000));
653
654 {
655 Packet c0 = *copy;
656 Packet c1 = *copy;
657 c0 = c1;
658 CHECK(&c0, 1, E(1, 0, 1000));
659 CHECK(&c1, 1, E(1, 0, 1000));
660 CHECK(copy, 1, E(1, 0, 1000));
662 CHECK(&c0, 2, E(1, 0, 1000), E(10, 0, 1000));
663 CHECK(&c1, 1, E(1, 0, 1000));
664 CHECK(copy, 1, E(1, 0, 1000));
665 }
666
667 Ptr<Packet> frag0 = p->CreateFragment(0, 10);
668 Ptr<Packet> frag1 = p->CreateFragment(10, 90);
669 Ptr<const Packet> frag2 = p->CreateFragment(100, 900);
670 frag0->AddByteTag(ATestTag<3>());
671 CHECK(frag0, 3, E(1, 0, 10), E(2, 0, 10), E(3, 0, 10));
672 frag1->AddByteTag(ATestTag<4>());
673 CHECK(frag1, 3, E(1, 0, 90), E(2, 0, 90), E(4, 0, 90));
674 frag2->AddByteTag(ATestTag<5>());
675 CHECK(frag2, 3, E(1, 0, 900), E(2, 0, 900), E(5, 0, 900));
676
677 frag1->AddAtEnd(frag2);
678 CHECK(frag1,
679 6,
680 E(1, 0, 90),
681 E(2, 0, 90),
682 E(4, 0, 90),
683 E(1, 90, 990),
684 E(2, 90, 990),
685 E(5, 90, 990));
686
687 CHECK(frag0, 3, E(1, 0, 10), E(2, 0, 10), E(3, 0, 10));
688 frag0->AddAtEnd(frag1);
689 CHECK(frag0,
690 9,
691 E(1, 0, 10),
692 E(2, 0, 10),
693 E(3, 0, 10),
694 E(1, 10, 100),
695 E(2, 10, 100),
696 E(4, 10, 100),
697 E(1, 100, 1000),
698 E(2, 100, 1000),
699 E(5, 100, 1000));
700
701 // force caching a buffer of the right size.
702 frag0 = Create<Packet>(1000);
703 frag0->AddHeader(ATestHeader<10>());
704 frag0 = nullptr;
705
706 p = Create<Packet>(1000);
707 p->AddByteTag(ATestTag<20>());
708 CHECK(p, 1, E(20, 0, 1000));
709 frag0 = p->CreateFragment(10, 90);
710 CHECK(p, 1, E(20, 0, 1000));
711 CHECK(frag0, 1, E(20, 0, 90));
712 p = nullptr;
713 frag0->AddHeader(ATestHeader<10>());
714 CHECK(frag0, 1, E(20, 10, 100));
715
716 {
717 Ptr<Packet> tmp = Create<Packet>(100);
718 tmp->AddByteTag(ATestTag<20>());
719 CHECK(tmp, 1, E(20, 0, 100));
720 tmp->AddHeader(ATestHeader<10>());
721 CHECK(tmp, 1, E(20, 10, 110));
723 tmp->RemoveHeader(h);
724 CHECK(tmp, 1, E(20, 0, 100));
725 tmp->AddHeader(ATestHeader<10>());
726 CHECK(tmp, 1, E(20, 10, 110));
727
728 tmp = Create<Packet>(100);
729 tmp->AddByteTag(ATestTag<20>());
730 CHECK(tmp, 1, E(20, 0, 100));
731 tmp->AddTrailer(ATestTrailer<10>());
732 CHECK(tmp, 1, E(20, 0, 100));
734 tmp->RemoveTrailer(t);
735 CHECK(tmp, 1, E(20, 0, 100));
736 tmp->AddTrailer(ATestTrailer<10>());
737 CHECK(tmp, 1, E(20, 0, 100));
738 }
739
740 {
741 Ptr<Packet> tmp = Create<Packet>(0);
742 tmp->AddHeader(ATestHeader<156>());
743 tmp->AddByteTag(ATestTag<20>());
744 CHECK(tmp, 1, E(20, 0, 156));
745 tmp->RemoveAtStart(120);
746 CHECK(tmp, 1, E(20, 0, 36));
747 Ptr<Packet> a = Create<Packet>(0);
748 a->AddAtEnd(tmp);
749 CHECK(a, 1, E(20, 0, 36));
750 }
751
752 {
753 Ptr<Packet> tmp = Create<Packet>(0);
754 tmp->AddByteTag(ATestTag<20>());
755 CHECK(tmp, 0, E(20, 0, 0));
756 }
757 {
758 Ptr<Packet> tmp = Create<Packet>(1000);
759 tmp->AddByteTag(ATestTag<20>());
760 CHECK(tmp, 1, E(20, 0, 1000));
761 tmp->RemoveAtStart(1000);
762 CHECK(tmp, 0, E(0, 0, 0));
763 Ptr<Packet> a = Create<Packet>(10);
764 a->AddByteTag(ATestTag<10>());
765 CHECK(a, 1, E(10, 0, 10));
766 tmp->AddAtEnd(a);
767 CHECK(tmp, 1, E(10, 0, 10));
768 }
769
770 {
771 Packet p;
772 ATestTag<10> a;
773 p.AddPacketTag(a);
774 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(a), true, "trivial");
775 ATestTag<11> b;
776 p.AddPacketTag(b);
777 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(b), true, "trivial");
778 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(a), true, "trivial");
779 Packet copy = p;
780 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(b), true, "trivial");
781 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(a), true, "trivial");
782 ATestTag<12> c;
783 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(c), false, "trivial");
784 copy.AddPacketTag(c);
785 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(c), true, "trivial");
786 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(b), true, "trivial");
787 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(a), true, "trivial");
788 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(c), false, "trivial");
789 copy.RemovePacketTag(b);
790 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(b), false, "trivial");
791 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(b), true, "trivial");
792 p.RemovePacketTag(a);
793 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(a), false, "trivial");
794 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(a), true, "trivial");
795 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(c), false, "trivial");
796 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(c), true, "trivial");
798 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(b), false, "trivial");
799 }
800
801 /* Test Serialization and Deserialization of Packet with PacketTag data */
802 {
803 Ptr<Packet> p1 = Create<Packet>(1000);
804 ;
805 ATestTag<10> a1(65);
806 ATestTag<11> b1(66);
807 ATestTag<12> c1(67);
808
809 p1->AddPacketTag(a1);
810 p1->AddPacketTag(b1);
811 p1->AddPacketTag(c1);
812
813 uint32_t serializedSize = p1->GetSerializedSize();
814 auto buffer = new uint8_t[serializedSize + 16];
815 p1->Serialize(buffer, serializedSize);
816
817 Ptr<Packet> p2 = Create<Packet>(buffer, serializedSize, true);
818
819 delete[] buffer;
820
821 ATestTag<10> a2;
822 ATestTag<11> b2;
823 ATestTag<12> c2;
824
825 NS_TEST_EXPECT_MSG_EQ(p2->PeekPacketTag(a2), true, "trivial");
826 NS_TEST_EXPECT_MSG_EQ(a2.GetData(), 65, "trivial");
827 NS_TEST_EXPECT_MSG_EQ(p2->PeekPacketTag(b2), true, "trivial");
828 NS_TEST_EXPECT_MSG_EQ(b2.GetData(), 66, "trivial");
829 NS_TEST_EXPECT_MSG_EQ(p2->PeekPacketTag(c2), true, "trivial");
830 NS_TEST_EXPECT_MSG_EQ(c2.GetData(), 67, "trivial");
831 }
832
833 /* Test Serialization and Deserialization of Packet with ByteTag data */
834 {
835 Ptr<Packet> p1 = Create<Packet>(1000);
836 ;
837
838 ATestTag<10> a1(65);
839 ATestTag<11> b1(66);
840 ATestTag<12> c1(67);
841
842 p1->AddByteTag(a1);
843 p1->AddByteTag(b1);
844 p1->AddByteTag(c1);
845
846 CHECK(p1, 3, E(10, 0, 1000), E(11, 0, 1000), E(12, 0, 1000));
847
848 uint32_t serializedSize = p1->GetSerializedSize();
849 auto buffer = new uint8_t[serializedSize];
850 p1->Serialize(buffer, serializedSize);
851
852 Ptr<Packet> p2 = Create<Packet>(buffer, serializedSize, true);
853
854 delete[] buffer;
855
856 CHECK_DATA(p2,
857 3,
858 E_DATA(10, 0, 1000, 65),
859 E_DATA(11, 0, 1000, 66),
860 E_DATA(12, 0, 1000, 67));
861 }
862
863 {
864 /// \internal
865 /// See \bugid{572}
866 Ptr<Packet> tmp = Create<Packet>(1000);
867 tmp->AddByteTag(ATestTag<20>());
868 CHECK(tmp, 1, E(20, 0, 1000));
869 tmp->AddHeader(ATestHeader<2>());
870 CHECK(tmp, 1, E(20, 2, 1002));
871 tmp->RemoveAtStart(1);
872 CHECK(tmp, 1, E(20, 1, 1001));
873#if 0
874 tmp->PeekData ();
875 CHECK (tmp, 1, E (20, 1, 1001));
876#endif
877 }
878
879 /* Test reducing tagged packet size and increasing it back. */
880 {
881 Ptr<Packet> tmp = Create<Packet>(0);
882 tmp->AddHeader(ATestHeader<100>());
883 tmp->AddByteTag(ATestTag<25>());
884 CHECK(tmp, 1, E(25, 0, 100));
885 tmp->RemoveAtStart(50);
886 CHECK(tmp, 1, E(25, 0, 50));
887 tmp->AddHeader(ATestHeader<50>());
888 CHECK(tmp, 1, E(25, 50, 100));
889 }
890
891 /* Similar test case, but using trailer instead of header. */
892 {
893 Ptr<Packet> tmp = Create<Packet>(0);
894 tmp->AddTrailer(ATestTrailer<100>());
895 tmp->AddByteTag(ATestTag<25>());
896 CHECK(tmp, 1, E(25, 0, 100));
897 tmp->RemoveAtEnd(50);
898 CHECK(tmp, 1, E(25, 0, 50));
899 tmp->AddTrailer(ATestTrailer<50>());
900 CHECK(tmp, 1, E(25, 0, 50));
901 }
902
903 /* Test reducing tagged packet size and increasing it by half. */
904 {
905 Ptr<Packet> tmp = Create<Packet>(0);
906 tmp->AddHeader(ATestHeader<100>());
907 tmp->AddByteTag(ATestTag<25>());
908 CHECK(tmp, 1, E(25, 0, 100));
909 tmp->RemoveAtStart(50);
910 CHECK(tmp, 1, E(25, 0, 50));
911 tmp->AddHeader(ATestHeader<25>());
912 CHECK(tmp, 1, E(25, 25, 75));
913 }
914
915 /* Similar test case, but using trailer instead of header. */
916 {
917 Ptr<Packet> tmp = Create<Packet>(0);
918 tmp->AddTrailer(ATestTrailer<100>());
919 tmp->AddByteTag(ATestTag<25>());
920 CHECK(tmp, 1, E(25, 0, 100));
921 tmp->RemoveAtEnd(50);
922 CHECK(tmp, 1, E(25, 0, 50));
923 tmp->AddTrailer(ATestTrailer<25>());
924 CHECK(tmp, 1, E(25, 0, 50));
925 }
926
927 /* Test AddPaddingAtEnd. */
928 {
929 Ptr<Packet> tmp = Create<Packet>(0);
930 tmp->AddTrailer(ATestTrailer<100>());
931 tmp->AddByteTag(ATestTag<25>());
932 CHECK(tmp, 1, E(25, 0, 100));
933 tmp->RemoveAtEnd(50);
934 CHECK(tmp, 1, E(25, 0, 50));
935 tmp->AddPaddingAtEnd(50);
936 CHECK(tmp, 1, E(25, 0, 50));
937 }
938
939 /* Test reducing tagged packet size and increasing it back,
940 * now using padding bytes to avoid triggering dirty state
941 * in virtual buffer
942 */
943 {
944 Ptr<Packet> tmp = Create<Packet>(100);
945 tmp->AddByteTag(ATestTag<25>());
946 CHECK(tmp, 1, E(25, 0, 100));
947 tmp->RemoveAtEnd(50);
948 CHECK(tmp, 1, E(25, 0, 50));
949 tmp->AddPaddingAtEnd(50);
950 CHECK(tmp, 1, E(25, 0, 50));
951 }
952
953 /* Test ALargeTestTag */
954 {
955 Ptr<Packet> tmp = Create<Packet>(0);
957 tmp->AddPacketTag(a);
958 }
959}
960
961/**
962 * \ingroup network-test
963 * \ingroup tests
964 *
965 * Packet Tag list unit tests.
966 */
968{
969 public:
971 ~PacketTagListTest() override;
972
973 private:
974 void DoRun() override;
975 /**
976 * Checks against a reference PacketTagList
977 * \param ref Reference
978 * \param t List to test
979 * \param msg Message
980 * \param miss Expected miss/hit
981 */
982 void CheckRef(const PacketTagList& ref, ATestTagBase& t, const char* msg, bool miss = false);
983 /**
984 * Checks against a reference PacketTagList
985 * \param ref Reference
986 * \param msg Message
987 * \param miss Expected miss/hit
988 */
989 void CheckRefList(const PacketTagList& ref, const char* msg, int miss = 0);
990
991 /**
992 * Prints the remove time
993 * \param ref Reference.
994 * \param t List to test.
995 * \param msg Message - prints on cout if msg is not null.
996 * \return the ticks to remove the tags.
997 */
998 int RemoveTime(const PacketTagList& ref, ATestTagBase& t, const char* msg = nullptr);
999
1000 /**
1001 * Prints the remove time
1002 * \param verbose prints on cout if verbose is true.
1003 * \return the ticks to remove the tags.
1004 */
1005 int AddRemoveTime(const bool verbose = false);
1006};
1007
1009 : TestCase("PacketTagListTest: ")
1010{
1011}
1012
1014{
1015}
1016
1017void
1018PacketTagListTest::CheckRef(const PacketTagList& ref, ATestTagBase& t, const char* msg, bool miss)
1019{
1020 int expect = t.GetData(); // the value we should find
1021 bool found = ref.Peek(t); // rewrites t with actual value
1022 NS_TEST_EXPECT_MSG_EQ(found, !miss, msg << ": ref contains " << t.GetTypeId().GetName());
1023 if (found)
1024 {
1026 expect,
1027 msg << ": ref " << t.GetTypeId().GetName() << " = " << expect);
1028 }
1029}
1030
1031// A set of tags with data value 1, to check COW
1032#define MAKE_TEST_TAGS \
1033 ATestTag<1> t1(1); \
1034 ATestTag<2> t2(1); \
1035 ATestTag<3> t3(1); \
1036 ATestTag<4> t4(1); \
1037 ATestTag<5> t5(1); \
1038 ATestTag<6> t6(1); \
1039 ATestTag<7> t7(1); \
1040 constexpr int TAG_LAST [[maybe_unused]] = 7; /* length of ref PacketTagList */
1041
1042void
1043PacketTagListTest::CheckRefList(const PacketTagList& ptl, const char* msg, int miss /* = 0 */)
1044{
1046 CheckRef(ptl, t1, msg, miss == 1);
1047 CheckRef(ptl, t2, msg, miss == 2);
1048 CheckRef(ptl, t3, msg, miss == 3);
1049 CheckRef(ptl, t4, msg, miss == 4);
1050 CheckRef(ptl, t5, msg, miss == 5);
1051 CheckRef(ptl, t6, msg, miss == 6);
1052 CheckRef(ptl, t7, msg, miss == 7);
1053}
1054
1055int
1056PacketTagListTest::RemoveTime(const PacketTagList& ref, ATestTagBase& t, const char* msg /* = 0 */)
1057{
1058 const int reps = 10000;
1059 std::vector<PacketTagList> ptv(reps, ref);
1060 int start = clock();
1061 for (int i = 0; i < reps; ++i)
1062 {
1063 ptv[i].Remove(t);
1064 }
1065 int stop = clock();
1066 int delta = stop - start;
1067 if (msg)
1068 {
1069 std::cout << GetName() << "remove time: " << msg << ": " << std::setw(8) << delta
1070 << " ticks to remove " << reps << " times" << std::endl;
1071 }
1072 return delta;
1073}
1074
1075int
1077{
1078 const int reps = 100000;
1079 PacketTagList ptl;
1080 ATestTag<2> t(2);
1081 int start = clock();
1082 for (int i = 0; i < reps; ++i)
1083 {
1084 ptl.Add(t);
1085 ptl.Remove(t);
1086 }
1087 int stop = clock();
1088 int delta = stop - start;
1089 if (verbose)
1090 {
1091 std::cout << GetName() << "add/remove time: " << std::setw(8) << delta
1092 << " ticks to add+remove " << reps << " times" << std::endl;
1093 }
1094 return delta;
1095}
1096
1097void
1099{
1100 std::cout << GetName() << "begin" << std::endl;
1101
1103
1104 PacketTagList ref; // empty list
1105 ref.Add(t1); // last
1106 ref.Add(t2); // post merge
1107 ref.Add(t3); // merge successor
1108 ref.Add(t4); // merge
1109 ref.Add(t5); // merge precursor
1110 ref.Add(t6); // pre-merge
1111 ref.Add(t7); // first
1112
1113 // Peek
1114 {
1115 std::cout << GetName() << "check Peek (missing tag) returns false" << std::endl;
1116 ATestTag<10> t10;
1117 NS_TEST_EXPECT_MSG_EQ(ref.Peek(t10), false, "missing tag");
1118 }
1119
1120 // Copy ctor, assignment
1121 {
1122 std::cout << GetName() << "check copy and assignment" << std::endl;
1123 {
1124 // Test copy constructor
1125 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
1126 PacketTagList ptl(ref);
1127 CheckRefList(ref, "copy ctor orig");
1128 CheckRefList(ptl, "copy ctor copy");
1129 }
1130 {
1131 // Test copy constructor
1132 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
1133 PacketTagList ptl = ref;
1134 CheckRefList(ref, "assignment orig");
1135 CheckRefList(ptl, "assignment copy");
1136 }
1137 }
1138
1139 // Removal
1140 {
1141#define RemoveCheck(n) \
1142 PacketTagList p##n = ref; \
1143 p##n.Remove(t##n); \
1144 CheckRefList(ref, "remove " #n " orig"); \
1145 CheckRefList(p##n, "remove " #n " copy", n);
1146
1147 // Remove single tags from list
1148 {
1149 std::cout << GetName() << "check removal of each tag" << std::endl;
1150 RemoveCheck(1);
1151 RemoveCheck(2);
1152 RemoveCheck(3);
1153 RemoveCheck(4);
1154 RemoveCheck(5);
1155 RemoveCheck(6);
1156 RemoveCheck(7);
1157 }
1158
1159 // Remove in the presence of a merge
1160 {
1161 std::cout << GetName() << "check removal doesn't disturb merge " << std::endl;
1162 PacketTagList ptl = ref;
1163 ptl.Remove(t7);
1164 ptl.Remove(t6);
1165 ptl.Remove(t5);
1166
1167 PacketTagList mrg = ptl; // merged list
1168 ATestTag<8> m5(1);
1169 mrg.Add(m5); // ptl and mrg differ
1170 ptl.Add(t5);
1171 ptl.Add(t6);
1172 ptl.Add(t7);
1173
1174 CheckRefList(ref, "post merge, orig");
1175 CheckRefList(ptl, "post merge, long chain");
1176 const char* msg = "post merge, short chain";
1177 CheckRef(mrg, t1, msg, false);
1178 CheckRef(mrg, t2, msg, false);
1179 CheckRef(mrg, t3, msg, false);
1180 CheckRef(mrg, t4, msg, false);
1181 CheckRef(mrg, m5, msg, false);
1182 }
1183#undef RemoveCheck
1184 } // Removal
1185
1186 // Replace
1187 {
1188 std::cout << GetName() << "check replacing each tag" << std::endl;
1189
1190#define ReplaceCheck(n) \
1191 t##n.m_data = 2; \
1192 { \
1193 PacketTagList p##n = ref; \
1194 p##n.Replace(t##n); \
1195 CheckRefList(ref, "replace " #n " orig"); \
1196 CheckRef(p##n, t##n, "replace " #n " copy"); \
1197 }
1198
1199 ReplaceCheck(1);
1200 ReplaceCheck(2);
1201 ReplaceCheck(3);
1202 ReplaceCheck(4);
1203 ReplaceCheck(5);
1204 ReplaceCheck(6);
1205 ReplaceCheck(7);
1206 }
1207
1208 // Timing
1209 {
1210 std::cout << GetName() << "add+remove timing" << std::endl;
1211 int flm = std::numeric_limits<int>::max();
1212 const int nIterations = 100;
1213 for (int i = 0; i < nIterations; ++i)
1214 {
1215 int now = AddRemoveTime();
1216 if (now < flm)
1217 {
1218 flm = now;
1219 }
1220 }
1221 std::cout << GetName() << "min add+remove time: " << std::setw(8) << flm << " ticks"
1222 << std::endl;
1223
1224 std::cout << GetName() << "remove timing" << std::endl;
1225 // tags numbered from 1, so add one for (unused) entry at 0
1226 std::vector<int> rmn(TAG_LAST + 1, std::numeric_limits<int>::max());
1227 for (int i = 0; i < nIterations; ++i)
1228 {
1229 for (int j = 1; j <= TAG_LAST; ++j)
1230 {
1231 int now = 0;
1232 switch (j)
1233 {
1234 case 7:
1235 now = RemoveTime(ref, t7);
1236 break;
1237 case 6:
1238 now = RemoveTime(ref, t6);
1239 break;
1240 case 5:
1241 now = RemoveTime(ref, t5);
1242 break;
1243 case 4:
1244 now = RemoveTime(ref, t4);
1245 break;
1246 case 3:
1247 now = RemoveTime(ref, t3);
1248 break;
1249 case 2:
1250 now = RemoveTime(ref, t2);
1251 break;
1252 case 1:
1253 now = RemoveTime(ref, t1);
1254 break;
1255 } // switch
1256
1257 if (now < rmn[j])
1258 {
1259 rmn[j] = now;
1260 }
1261 } // for tag j
1262 } // for iteration i
1263 for (int j = TAG_LAST; j > 0; --j)
1264 {
1265 std::cout << GetName() << "min remove time: t" << j << ": " << std::setw(8) << rmn[j]
1266 << " ticks" << std::endl;
1267 }
1268 } // Timing
1269}
1270
1271/**
1272 * \ingroup network-test
1273 * \ingroup tests
1274 *
1275 * \brief Packet TestSuite
1276 */
1278{
1279 public:
1281};
1282
1284 : TestSuite("packet", Type::UNIT)
1285{
1286 AddTestCase(new PacketTest, TestCase::Duration::QUICK);
1287 AddTestCase(new PacketTagListTest, TestCase::Duration::QUICK);
1288}
1289
1290static PacketTestSuite g_packetTestSuite; //!< Static variable for test initialization
Packet Tag list unit tests.
void CheckRefList(const PacketTagList &ref, const char *msg, int miss=0)
Checks against a reference PacketTagList.
int AddRemoveTime(const bool verbose=false)
Prints the remove time.
void DoRun() override
Implementation to actually run this TestCase.
void CheckRef(const PacketTagList &ref, ATestTagBase &t, const char *msg, bool miss=false)
Checks against a reference PacketTagList.
int RemoveTime(const PacketTagList &ref, ATestTagBase &t, const char *msg=nullptr)
Prints the remove time.
Packet unit tests.
void DoCheckData(Ptr< const Packet > p, uint32_t n,...)
Checks the packet and its data.
void DoRun() override
Implementation to actually run this TestCase.
void DoCheck(Ptr< const Packet > p, uint32_t n,...)
Checks the packet.
Packet TestSuite.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
uint32_t Deserialize(Buffer::Iterator iter) override
void Serialize(Buffer::Iterator iter) const override
void Print(std::ostream &os) const override
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
uint32_t Deserialize(Buffer::Iterator iter) override
void Serialize(Buffer::Iterator iter) const override
iterator in a Buffer instance
Definition: buffer.h:100
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
void Prev()
go backward by one byte
Definition: buffer.h:860
Identifies a byte tag and a set of bytes within a packet to which the tag applies.
Definition: packet.h:63
uint32_t GetEnd() const
The index is an offset from the start of the packet.
Definition: packet.cc:48
void GetTag(Tag &tag) const
Read the requested tag and store it in the user-provided tag instance.
Definition: packet.cc:54
uint32_t GetStart() const
The index is an offset from the start of the packet.
Definition: packet.cc:42
TypeId GetTypeId() const
Definition: packet.cc:36
Iterator over the set of byte tags in a packet.
Definition: packet.h:56
bool HasNext() const
Definition: packet.cc:72
Protocol header serialization and deserialization.
Definition: header.h:44
network packets
Definition: packet.h:239
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:967
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:960
void RemoveAllPacketTags()
Remove all packet tags.
Definition: packet.cc:990
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:915
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:983
List of the packet tags stored in a packet.
bool Remove(Tag &tag)
Remove (the first instance of) tag from the list.
void Add(const Tag &tag) const
Add a tag to the head of this branch.
bool Peek(Tag &tag) const
Find a tag and return its value.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
read and write tag data
Definition: tag-buffer.h:52
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:172
TAG_BUFFER_INLINE uint8_t ReadU8()
Definition: tag-buffer.h:196
tag a set of bytes in a packet
Definition: tag.h:39
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
std::string GetName() const
Definition: test.cc:373
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
Protocol trailer serialization and deserialization.
Definition: trailer.h:41
a unique identifier for an interface.
Definition: type-id.h:59
Callback< ObjectBase * > GetConstructor() const
Get the constructor callback.
Definition: type-id.cc:1085
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
std::string GetName() const
Get the name.
Definition: type-id.cc:992
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
Definition: test.h:667
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:252
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool verbose
#define LARGE_TAG_BUFFER_SIZE
static PacketTestSuite g_packetTestSuite
Static variable for test initialization.
#define CHECK(p, n,...)
#define E_DATA(name, start, end, data)
#define ReplaceCheck(n)
#define E(name, start, end)
#define CHECK_DATA(p, n,...)
#define RemoveCheck(n)
#define MAKE_TEST_TAGS
uint8_t data[writeSize]
Struct to hold the expected data in the packet.
Expected(uint32_t n_, uint32_t start_, uint32_t end_, uint8_t data_)
Constructor.
Expected(uint32_t n_, uint32_t start_, uint32_t end_)
Constructor.