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