A Discrete-Event Network Simulator
API
packet-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "ns3/packet.h"
21 #include "ns3/packet-tag-list.h"
22 #include "ns3/test.h"
23 #include "ns3/unused.h"
24 #include <limits> // std:numeric_limits
25 #include <string>
26 #include <cstdarg>
27 #include <iostream>
28 #include <iomanip>
29 #include <ctime>
30 
31 using namespace ns3;
32 
33 //-----------------------------------------------------------------------------
34 // Unit tests
35 //-----------------------------------------------------------------------------
36 namespace {
37 
46 class ATestTagBase : public Tag
47 {
48 public:
49  ATestTagBase () : m_error (false), m_data (0) {}
52  ATestTagBase (uint8_t data) : m_error (false), m_data (data) {}
57  static TypeId GetTypeId (void)
58  {
59  static TypeId tid = TypeId ("ATestTagBase")
60  .SetParent<Tag> ()
61  .SetGroupName ("Network")
62  .HideFromDocumentation ()
63  // No AddConstructor because this is an abstract class.
64  ;
65  return tid;
66  }
69  int GetData () const {
70  int result = (int)m_data;
71  return result;
72  }
73  bool m_error;
74  uint8_t m_data;
75 };
76 
85 template <int N>
86 class ATestTag : public ATestTagBase
87 {
88 public:
93  static TypeId GetTypeId (void) {
94  std::ostringstream oss;
95  oss << "anon::ATestTag<" << N << ">";
96  static TypeId tid = TypeId (oss.str ().c_str ())
97  .SetParent<ATestTagBase> ()
98  .SetGroupName ("Network")
101  ;
102  return tid;
103  }
104  virtual TypeId GetInstanceTypeId (void) const {
105  return GetTypeId ();
106  }
107  virtual uint32_t GetSerializedSize (void) const {
108  return N + sizeof(m_data);
109  }
110  virtual void Serialize (TagBuffer buf) const {
111  buf.WriteU8 (m_data);
112  for (uint32_t i = 0; i < N; ++i)
113  {
114  buf.WriteU8 (N);
115  }
116  }
117  virtual void Deserialize (TagBuffer buf) {
118  m_data = buf.ReadU8 ();
119  for (uint32_t i = 0; i < N; ++i)
120  {
121  uint8_t v = buf.ReadU8 ();
122  if (v != N)
123  {
124  m_error = true;
125  }
126  }
127  }
128  virtual void Print (std::ostream &os) const {
129  os << N << "(" << m_data << ")";
130  }
132  : ATestTagBase () {}
135  ATestTag (uint8_t data)
136  : ATestTagBase (data) {}
137 };
138 
139 // Previous versions of ns-3 limited the tag size to 20 bytes or less
140 // static const uint8_t LARGE_TAG_BUFFER_SIZE = 64;
141 #define LARGE_TAG_BUFFER_SIZE 64
142 
153 class ALargeTestTag : public Tag
154 {
155 public:
157  for (uint8_t i = 0; i < (LARGE_TAG_BUFFER_SIZE - 1); i++)
158  {
159  m_data.push_back (i);
160  }
161  m_size = LARGE_TAG_BUFFER_SIZE;
162  }
167  static TypeId GetTypeId (void)
168  {
169  static TypeId tid = TypeId ("ALargeTestTag")
170  .SetParent<Tag> ()
171  .SetGroupName ("Network")
172  .HideFromDocumentation ()
173  .AddConstructor<ALargeTestTag> ()
174  ;
175  return tid;
176  }
177  virtual TypeId GetInstanceTypeId (void) const {
178  return GetTypeId ();
179  }
180  virtual uint32_t GetSerializedSize (void) const {
181  return (uint32_t) m_size;
182  }
183  virtual void Serialize (TagBuffer buf) const {
184  buf.WriteU8 (m_size);
185  for (uint8_t i = 0; i < (m_size - 1); ++i)
186  {
187  buf.WriteU8 (m_data[i]);
188  }
189  }
190  virtual void Deserialize (TagBuffer buf) {
191  m_size = buf.ReadU8 ();
192  for (uint8_t i = 0; i < (m_size - 1); ++i)
193  {
194  uint8_t v = buf.ReadU8 ();
195  m_data.push_back (v);
196  }
197  }
198  virtual void Print (std::ostream &os) const {
199  os << "(" << (uint16_t) m_size << ")";
200  }
201 private:
202  uint8_t m_size;
203  std::vector<uint8_t> m_data;
204 };
205 
214 class ATestHeaderBase : public Header
215 {
216 public:
217  ATestHeaderBase () : Header (), m_error (false) {}
222  static TypeId GetTypeId (void)
223  {
224  static TypeId tid = TypeId ("ATestHeaderBase")
225  .SetParent<Header> ()
226  .SetGroupName ("Network")
227  .HideFromDocumentation ()
228  // No AddConstructor because this is an abstract class.
229  ;
230  return tid;
231  }
232  bool m_error;
233 };
234 
243 template <int N>
245 {
246 public:
251  static TypeId GetTypeId (void) {
252  std::ostringstream oss;
253  oss << "anon::ATestHeader<" << N << ">";
254  static TypeId tid = TypeId (oss.str ().c_str ())
255  .SetParent<ATestHeaderBase> ()
256  .SetGroupName ("Network")
259  ;
260  return tid;
261  }
262  virtual TypeId GetInstanceTypeId (void) const {
263  return GetTypeId ();
264  }
265  virtual uint32_t GetSerializedSize (void) const {
266  return N;
267  }
268  virtual void Serialize (Buffer::Iterator iter) const {
269  for (uint32_t i = 0; i < N; ++i)
270  {
271  iter.WriteU8 (N);
272  }
273  }
274  virtual uint32_t Deserialize (Buffer::Iterator iter) {
275  for (uint32_t i = 0; i < N; ++i)
276  {
277  uint8_t v = iter.ReadU8 ();
278  if (v != N)
279  {
280  m_error = true;
281  }
282  }
283  return N;
284  }
285  virtual void Print (std::ostream &os) const {
286  }
288  : ATestHeaderBase () {}
289 
290 };
291 
300 class ATestTrailerBase : public Trailer
301 {
302 public:
303  ATestTrailerBase () : Trailer (), m_error (false) {}
308  static TypeId GetTypeId (void)
309  {
310  static TypeId tid = TypeId ("ATestTrailerBase")
311  .SetParent<Trailer> ()
312  .SetGroupName ("Network")
313  .HideFromDocumentation ()
314  // No AddConstructor because this is an abstract class.
315  ;
316  return tid;
317  }
318  bool m_error;
319 };
320 
329 template <int N>
331 {
332 public:
337  static TypeId GetTypeId (void) {
338  std::ostringstream oss;
339  oss << "anon::ATestTrailer<" << N << ">";
340  static TypeId tid = TypeId (oss.str ().c_str ())
341  .SetParent<ATestTrailerBase> ()
342  .SetGroupName ("Network")
345  ;
346  return tid;
347  }
348  virtual TypeId GetInstanceTypeId (void) const {
349  return GetTypeId ();
350  }
351  virtual uint32_t GetSerializedSize (void) const {
352  return N;
353  }
354  virtual void Serialize (Buffer::Iterator iter) const {
355  iter.Prev (N);
356  for (uint32_t i = 0; i < N; ++i)
357  {
358  iter.WriteU8 (N);
359  }
360  }
361  virtual uint32_t Deserialize (Buffer::Iterator iter) {
362  iter.Prev (N);
363  for (uint32_t i = 0; i < N; ++i)
364  {
365  uint8_t v = iter.ReadU8 ();
366  if (v != N)
367  {
368  m_error = true;
369  }
370  }
371  return N;
372  }
373  virtual void Print (std::ostream &os) const {
374  }
376  : ATestTrailerBase () {}
377 
378 };
379 
388 struct Expected
389 {
396  Expected (uint32_t n_, uint32_t start_, uint32_t end_)
397  : n (n_), start (start_), end (end_), data(0) {}
398 
406  Expected (uint32_t n_, uint32_t start_, uint32_t end_, uint8_t data_)
407  : n (n_), start (start_), end (end_), data(data_) {}
408 
409  uint32_t n;
410  uint32_t start;
411  uint32_t end;
412  uint8_t data;
413 };
414 
415 }
416 
417 // tag name, start, end
418 #define E(name,start,end) name,start,end
419 
420 // tag name, start, end, data
421 #define E_DATA(name,start,end,data) name,start,end,data
422 
423 // Check byte tags on a packet, checks name, start, end
424 #define CHECK(p, n, ...) \
425  DoCheck (p, __FILE__, __LINE__, n, __VA_ARGS__)
426 
427 // Check byte tags on a packet, checks name, start, end, data
428 #define CHECK_DATA(p, n, ...) \
429  DoCheckData (p, __FILE__, __LINE__, n, __VA_ARGS__)
430 
437 class PacketTest : public TestCase
438 {
439 public:
440  PacketTest ();
441  virtual void DoRun (void);
442 private:
451  void DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
452  void DoCheckData (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
453 };
454 
455 
457  : TestCase ("Packet") {
458 }
459 
460 void
461 PacketTest::DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
462 {
463  std::vector<struct Expected> expected;
464  va_list ap;
465  va_start (ap, n);
466  for (uint32_t k = 0; k < n; ++k)
467  {
468  uint32_t N = va_arg (ap, uint32_t);
469  uint32_t start = va_arg (ap, uint32_t);
470  uint32_t end = va_arg (ap, uint32_t);
471  expected.push_back (Expected (N, start, end));
472  }
473  va_end (ap);
474 
476  uint32_t j = 0;
477  while (i.HasNext () && j < expected.size ())
478  {
479  ByteTagIterator::Item item = i.Next ();
480  struct Expected e = expected[j];
481  std::ostringstream oss;
482  oss << "anon::ATestTag<" << e.n << ">";
483  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetTypeId ().GetName (), oss.str (), "trivial", file, line);
484  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetStart (), e.start, "trivial", file, line);
485  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetEnd (), e.end, "trivial", file, line);
486  ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
487  NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
488  item.GetTag (*tag);
489  NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
490  delete tag;
491  j++;
492  }
493  NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
494  NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
495 }
496 
497 void
498 PacketTest::DoCheckData (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
499 {
500  std::vector<struct Expected> expected;
501  va_list ap;
502  va_start (ap, n);
503  for (uint32_t k = 0; k < n; ++k)
504  {
505  uint32_t N = va_arg (ap, uint32_t);
506  uint32_t start = va_arg (ap, uint32_t);
507  uint32_t end = va_arg (ap, uint32_t);
508  int data = va_arg (ap, int);
509  expected.push_back (Expected (N, start, end, data));
510  }
511  va_end (ap);
512 
514  uint32_t j = 0;
515  while (i.HasNext () && j < expected.size ())
516  {
517  ByteTagIterator::Item item = i.Next ();
518  struct Expected e = expected[j];
519  std::ostringstream oss;
520  oss << "anon::ATestTag<" << e.n << ">";
521  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetTypeId ().GetName (), oss.str (), "trivial", file, line);
522  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetStart (), e.start, "trivial", file, line);
523  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetEnd (), e.end, "trivial", file, line);
524  ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
525  NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
526  item.GetTag (*tag);
527  NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
528  NS_TEST_EXPECT_MSG_EQ (tag->GetData (), e.data, "trivial");
529  delete tag;
530  j++;
531  }
532  NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
533  NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
534 }
535 
536 void
538 {
539  Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
540  Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
541  Ptr<Packet> packet = Create<Packet> ();
542  packet->AddAtEnd (pkt1);
543  packet->AddAtEnd (pkt2);
544 
545  NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 11, "trivial");
546 
547  uint8_t *buf = new uint8_t[packet->GetSize ()];
548  packet->CopyData (buf, packet->GetSize ());
549 
550  std::string msg = std::string (reinterpret_cast<const char *>(buf),
551  packet->GetSize ());
552  delete [] buf;
553 
554  NS_TEST_EXPECT_MSG_EQ (msg, "hello world", "trivial");
555 
556 
557  Ptr<const Packet> p = Create<Packet> (1000);
558 
559  p->AddByteTag (ATestTag<1> ());
560  CHECK (p, 1, E (1, 0, 1000));
561  Ptr<const Packet> copy = p->Copy ();
562  CHECK (copy, 1, E (1, 0, 1000));
563 
564  p->AddByteTag (ATestTag<2> ());
565  CHECK (p, 2, E (1, 0, 1000), E (2, 0, 1000));
566  CHECK (copy, 1, E (1, 0, 1000));
567 
568  {
569  Packet c0 = *copy;
570  Packet c1 = *copy;
571  c0 = c1;
572  CHECK (&c0, 1, E (1, 0, 1000));
573  CHECK (&c1, 1, E (1, 0, 1000));
574  CHECK (copy, 1, E (1, 0, 1000));
575  c0.AddByteTag (ATestTag<10> ());
576  CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
577  CHECK (&c1, 1, E (1, 0, 1000));
578  CHECK (copy, 1, E (1, 0, 1000));
579  }
580 
581  Ptr<Packet> frag0 = p->CreateFragment (0, 10);
582  Ptr<Packet> frag1 = p->CreateFragment (10, 90);
583  Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
584  frag0->AddByteTag (ATestTag<3> ());
585  CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
586  frag1->AddByteTag (ATestTag<4> ());
587  CHECK (frag1, 3, E (1, 0, 90), E (2, 0, 90), E (4, 0, 90));
588  frag2->AddByteTag (ATestTag<5> ());
589  CHECK (frag2, 3, E (1, 0, 900), E (2, 0, 900), E (5, 0, 900));
590 
591  frag1->AddAtEnd (frag2);
592  CHECK (frag1, 6, E (1, 0, 90), E (2, 0, 90), E (4, 0, 90), E (1, 90, 990), E (2, 90, 990), E (5, 90, 990));
593 
594  CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
595  frag0->AddAtEnd (frag1);
596  CHECK (frag0, 9,
597  E (1, 0, 10), E (2, 0, 10), E (3, 0, 10),
598  E (1, 10, 100), E (2, 10, 100), E (4, 10, 100),
599  E (1, 100, 1000), E (2, 100, 1000), E (5, 100, 1000));
600 
601 
602  // force caching a buffer of the right size.
603  frag0 = Create<Packet> (1000);
604  frag0->AddHeader (ATestHeader<10> ());
605  frag0 = 0;
606 
607  p = Create<Packet> (1000);
608  p->AddByteTag (ATestTag<20> ());
609  CHECK (p, 1, E (20, 0, 1000));
610  frag0 = p->CreateFragment (10, 90);
611  CHECK (p, 1, E (20, 0, 1000));
612  CHECK (frag0, 1, E (20, 0, 90));
613  p = 0;
614  frag0->AddHeader (ATestHeader<10> ());
615  CHECK (frag0, 1, E (20, 10, 100));
616 
617  {
618  Ptr<Packet> tmp = Create<Packet> (100);
619  tmp->AddByteTag (ATestTag<20> ());
620  CHECK (tmp, 1, E (20, 0, 100));
621  tmp->AddHeader (ATestHeader<10> ());
622  CHECK (tmp, 1, E (20, 10, 110));
623  ATestHeader<10> h;
624  tmp->RemoveHeader (h);
625  CHECK (tmp, 1, E (20, 0, 100));
626  tmp->AddHeader (ATestHeader<10> ());
627  CHECK (tmp, 1, E (20, 10, 110));
628 
629  tmp = Create<Packet> (100);
630  tmp->AddByteTag (ATestTag<20> ());
631  CHECK (tmp, 1, E (20, 0, 100));
632  tmp->AddTrailer (ATestTrailer<10> ());
633  CHECK (tmp, 1, E (20, 0, 100));
634  ATestTrailer<10> t;
635  tmp->RemoveTrailer (t);
636  CHECK (tmp, 1, E (20, 0, 100));
637  tmp->AddTrailer (ATestTrailer<10> ());
638  CHECK (tmp, 1, E (20, 0, 100));
639 
640  }
641 
642  {
643  Ptr<Packet> tmp = Create<Packet> (0);
644  tmp->AddHeader (ATestHeader<156> ());
645  tmp->AddByteTag (ATestTag<20> ());
646  CHECK (tmp, 1, E (20, 0, 156));
647  tmp->RemoveAtStart (120);
648  CHECK (tmp, 1, E (20, 0, 36));
649  Ptr<Packet> a = Create<Packet> (0);
650  a->AddAtEnd (tmp);
651  CHECK (a, 1, E (20, 0, 36));
652  }
653 
654  {
655  Ptr<Packet> tmp = Create<Packet> (0);
656  tmp->AddByteTag (ATestTag<20> ());
657  CHECK (tmp, 0, E (20, 0, 0));
658  }
659  {
660  Ptr<Packet> tmp = Create<Packet> (1000);
661  tmp->AddByteTag (ATestTag<20> ());
662  CHECK (tmp, 1, E (20, 0, 1000));
663  tmp->RemoveAtStart (1000);
664  CHECK (tmp, 0, E (0,0,0));
665  Ptr<Packet> a = Create<Packet> (10);
666  a->AddByteTag (ATestTag<10> ());
667  CHECK (a, 1, E (10, 0, 10));
668  tmp->AddAtEnd (a);
669  CHECK (tmp, 1, E (10, 0, 10));
670  }
671 
672  {
673  Packet p;
674  ATestTag<10> a;
675  p.AddPacketTag (a);
676  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
677  ATestTag<11> b;
678  p.AddPacketTag (b);
679  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
680  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
681  Packet copy = p;
682  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
683  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
684  ATestTag<12> c;
685  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), false, "trivial");
686  copy.AddPacketTag (c);
687  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
688  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
689  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
690  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
691  copy.RemovePacketTag (b);
692  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), false, "trivial");
693  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
694  p.RemovePacketTag (a);
695  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), false, "trivial");
696  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
697  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
698  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
699  p.RemoveAllPacketTags ();
700  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), false, "trivial");
701  }
702 
703  /* Test Serialization and Deserialization of Packet with PacketTag data */
704  {
705  Ptr<Packet> p1 = Create<Packet> (1000);;
706  ATestTag<10> a1(65);
707  ATestTag<11> b1(66);
708  ATestTag<12> c1(67);
709 
710  p1->AddPacketTag (a1);
711  p1->AddPacketTag (b1);
712  p1->AddPacketTag (c1);
713 
714  uint32_t serializedSize = p1->GetSerializedSize ();
715  uint8_t* buffer = new uint8_t[serializedSize + 16];
716  p1->Serialize (buffer, serializedSize);
717 
718  Ptr<Packet> p2 = Create<Packet> (buffer, serializedSize, true);
719 
720  delete [] buffer;
721 
722  ATestTag<10> a2;
723  ATestTag<11> b2;
724  ATestTag<12> c2;
725 
726  NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(a2), true, "trivial");
727  NS_TEST_EXPECT_MSG_EQ (a2.GetData (), 65, "trivial");
728  NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(b2), true, "trivial");
729  NS_TEST_EXPECT_MSG_EQ (b2.GetData (), 66, "trivial");
730  NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(c2), true, "trivial");
731  NS_TEST_EXPECT_MSG_EQ (c2.GetData (), 67, "trivial");
732  }
733 
734  /* Test Serialization and Deserialization of Packet with ByteTag data */
735  {
736  Ptr<Packet> p1 = Create<Packet> (1000);;
737 
738  ATestTag<10> a1(65);
739  ATestTag<11> b1(66);
740  ATestTag<12> c1(67);
741 
742  p1->AddByteTag (a1);
743  p1->AddByteTag (b1);
744  p1->AddByteTag (c1);
745 
746  CHECK (p1, 3, E (10, 0, 1000), E (11, 0, 1000), E (12, 0, 1000));
747 
748  uint32_t serializedSize = p1->GetSerializedSize ();
749  uint8_t* buffer = new uint8_t[serializedSize];
750  p1->Serialize (buffer, serializedSize);
751 
752  Ptr<Packet> p2 = Create<Packet> (buffer, serializedSize, true);
753 
754  delete [] buffer;
755 
756  CHECK_DATA (p2, 3, E_DATA (10, 0, 1000, 65), E_DATA (11, 0, 1000, 66), E_DATA (12, 0, 1000, 67));
757  }
758 
759  {
762  Ptr<Packet> tmp = Create<Packet> (1000);
763  tmp->AddByteTag (ATestTag<20> ());
764  CHECK (tmp, 1, E (20, 0, 1000));
765  tmp->AddHeader (ATestHeader<2> ());
766  CHECK (tmp, 1, E (20, 2, 1002));
767  tmp->RemoveAtStart (1);
768  CHECK (tmp, 1, E (20, 1, 1001));
769 #if 0
770  tmp->PeekData ();
771  CHECK (tmp, 1, E (20, 1, 1001));
772 #endif
773  }
774 
775  /* Test reducing tagged packet size and increasing it back. */
776  {
777  Ptr<Packet> tmp = Create<Packet> (0);
778  tmp->AddHeader (ATestHeader<100> ());
779  tmp->AddByteTag (ATestTag<25> ());
780  CHECK (tmp, 1, E (25, 0, 100));
781  tmp->RemoveAtStart (50);
782  CHECK (tmp, 1, E (25, 0, 50));
783  tmp->AddHeader (ATestHeader<50> ());
784  CHECK (tmp, 1, E (25, 50, 100));
785  }
786 
787  /* Similar test case, but using trailer instead of header. */
788  {
789  Ptr<Packet> tmp = Create<Packet> (0);
790  tmp->AddTrailer (ATestTrailer<100> ());
791  tmp->AddByteTag (ATestTag<25> ());
792  CHECK (tmp, 1, E (25, 0, 100));
793  tmp->RemoveAtEnd (50);
794  CHECK (tmp, 1, E (25, 0, 50));
795  tmp->AddTrailer (ATestTrailer<50> ());
796  CHECK (tmp, 1, E (25, 0, 50));
797  }
798 
799  /* Test reducing tagged packet size and increasing it by half. */
800  {
801  Ptr<Packet> tmp = Create<Packet> (0);
802  tmp->AddHeader (ATestHeader<100> ());
803  tmp->AddByteTag (ATestTag<25> ());
804  CHECK (tmp, 1, E (25, 0, 100));
805  tmp->RemoveAtStart (50);
806  CHECK (tmp, 1, E (25, 0, 50));
807  tmp->AddHeader (ATestHeader<25> ());
808  CHECK (tmp, 1, E (25, 25, 75));
809  }
810 
811  /* Similar test case, but using trailer instead of header. */
812  {
813  Ptr<Packet> tmp = Create<Packet> (0);
814  tmp->AddTrailer (ATestTrailer<100> ());
815  tmp->AddByteTag (ATestTag<25> ());
816  CHECK (tmp, 1, E (25, 0, 100));
817  tmp->RemoveAtEnd (50);
818  CHECK (tmp, 1, E (25, 0, 50));
819  tmp->AddTrailer (ATestTrailer<25> ());
820  CHECK (tmp, 1, E (25, 0, 50));
821  }
822 
823  /* Test AddPaddingAtEnd. */
824  {
825  Ptr<Packet> tmp = Create<Packet> (0);
826  tmp->AddTrailer (ATestTrailer<100> ());
827  tmp->AddByteTag (ATestTag<25> ());
828  CHECK (tmp, 1, E (25, 0, 100));
829  tmp->RemoveAtEnd (50);
830  CHECK (tmp, 1, E (25, 0, 50));
831  tmp->AddPaddingAtEnd (50);
832  CHECK (tmp, 1, E (25, 0, 50));
833  }
834 
835  /* Test reducing tagged packet size and increasing it back,
836  * now using padding bytes to avoid triggering dirty state
837  * in virtual buffer
838  */
839  {
840  Ptr<Packet> tmp = Create<Packet> (100);
841  tmp->AddByteTag (ATestTag<25> ());
842  CHECK (tmp, 1, E (25, 0, 100));
843  tmp->RemoveAtEnd (50);
844  CHECK (tmp, 1, E (25, 0, 50));
845  tmp->AddPaddingAtEnd (50);
846  CHECK (tmp, 1, E (25, 0, 50));
847  }
848 
849  /* Test ALargeTestTag */
850  {
851  Ptr<Packet> tmp = Create<Packet> (0);
852  ALargeTestTag a;
853  tmp->AddPacketTag (a);
854  }
855 }
856 
864 {
865 public:
867  virtual ~PacketTagListTest ();
868 private:
869  void DoRun (void);
877  void CheckRef (const PacketTagList & ref,
878  ATestTagBase & t,
879  const char * msg,
880  bool miss = false);
887  void CheckRefList (const PacketTagList & ref,
888  const char * msg,
889  int miss = 0);
890 
898  int RemoveTime (const PacketTagList & ref,
899  ATestTagBase & t,
900  const char * msg = 0);
901 
907  int AddRemoveTime (const bool verbose = false);
908 };
909 
911  : TestCase ("PacketTagListTest: ")
912 {
913 }
914 
916 {
917 }
918 
919 void
921  ATestTagBase & t,
922  const char * msg,
923  bool miss)
924 {
925  int expect = t.GetData (); // the value we should find
926  bool found = ref.Peek (t); // rewrites t with actual value
927  NS_TEST_EXPECT_MSG_EQ (found, !miss,
928  msg << ": ref contains "
929  << t.GetTypeId ().GetName ());
930  if (found) {
931  NS_TEST_EXPECT_MSG_EQ (t.GetData (), expect,
932  msg << ": ref " << t.GetTypeId ().GetName ()
933  << " = " << expect);
934  }
935 }
936 
937  // A set of tags with data value 1, to check COW
938 #define MAKE_TEST_TAGS \
939  ATestTag<1> t1 (1); \
940  ATestTag<2> t2 (1); \
941  ATestTag<3> t3 (1); \
942  ATestTag<4> t4 (1); \
943  ATestTag<5> t5 (1); \
944  ATestTag<6> t6 (1); \
945  ATestTag<7> t7 (1); \
946  const int tagLast = 7; /* length of ref PacketTagList */ \
947  NS_UNUSED (tagLast) /* silence warnings */
948 
949 
950 
951 void
953  const char * msg,
954  int miss /* = 0 */)
955 {
957  CheckRef (ptl, t1, msg, miss == 1);
958  CheckRef (ptl, t2, msg, miss == 2);
959  CheckRef (ptl, t3, msg, miss == 3);
960  CheckRef (ptl, t4, msg, miss == 4);
961  CheckRef (ptl, t5, msg, miss == 5);
962  CheckRef (ptl, t6, msg, miss == 6);
963  CheckRef (ptl, t7, msg, miss == 7);
964 }
965 
966 int
968  ATestTagBase & t,
969  const char * msg /* = 0 */)
970 {
971  const int reps = 10000;
972  std::vector< PacketTagList > ptv(reps, ref);
973  int start = clock ();
974  for (int i = 0; i < reps; ++i) {
975  ptv[i].Remove (t);
976  }
977  int stop = clock ();
978  int delta = stop - start;
979  if (msg) {
980  std::cout << GetName () << "remove time: " << msg << ": " << std::setw (8)
981  << delta << " ticks to remove "
982  << reps << " times"
983  << std::endl;
984  }
985  return delta;
986 }
987 
988 int
989 PacketTagListTest::AddRemoveTime (const bool verbose /* = false */)
990 {
991  const int reps = 100000;
992  PacketTagList ptl;
993  ATestTag <2> t(2);
994  int start = clock ();
995  for (int i = 0; i < reps; ++i) {
996  ptl.Add (t);
997  ptl.Remove (t);
998  }
999  int stop = clock ();
1000  int delta = stop - start;
1001  if (verbose) {
1002  std::cout << GetName () << "add/remove time: " << std::setw (8)
1003  << delta << " ticks to add+remove "
1004  << reps << " times"
1005  << std::endl;
1006  }
1007  return delta;
1008 }
1009 
1010 void
1012 {
1013  std::cout << GetName () << "begin" << std::endl;
1014 
1015  MAKE_TEST_TAGS ;
1016 
1017  PacketTagList ref; // empty list
1018  ref.Add (t1); // last
1019  ref.Add (t2); // post merge
1020  ref.Add (t3); // merge successor
1021  ref.Add (t4); // merge
1022  ref.Add (t5); // merge precursor
1023  ref.Add (t6); // pre-merge
1024  ref.Add (t7); // first
1025 
1026  { // Peek
1027  std::cout << GetName () << "check Peek (missing tag) returns false"
1028  << std::endl;
1029  ATestTag<10> t10;
1030  NS_TEST_EXPECT_MSG_EQ (ref.Peek (t10), false, "missing tag");
1031  }
1032 
1033  { // Copy ctor, assignment
1034  std::cout << GetName () << "check copy and assignment" << std::endl;
1035  { PacketTagList ptl (ref);
1036  CheckRefList (ref, "copy ctor orig");
1037  CheckRefList (ptl, "copy ctor copy");
1038  }
1039  { PacketTagList ptl = ref;
1040  CheckRefList (ref, "assignment orig");
1041  CheckRefList (ptl, "assignment copy");
1042  }
1043  }
1044 
1045  { // Removal
1046 # define RemoveCheck(n) \
1047  { PacketTagList p ## n = ref; \
1048  p ## n .Remove ( t ## n ); \
1049  CheckRefList (ref, "remove " #n " orig"); \
1050  CheckRefList (p ## n, "remove " #n " copy", n); \
1051  }
1052 
1053  { // Remove single tags from list
1054  std::cout << GetName () << "check removal of each tag" << std::endl;
1055  RemoveCheck (1);
1056  RemoveCheck (2);
1057  RemoveCheck (3);
1058  RemoveCheck (4);
1059  RemoveCheck (5);
1060  RemoveCheck (6);
1061  RemoveCheck (7);
1062  }
1063 
1064  { // Remove in the presence of a merge
1065  std::cout << GetName () << "check removal doesn't disturb merge "
1066  << std::endl;
1067  PacketTagList ptl = ref;
1068  ptl.Remove (t7);
1069  ptl.Remove (t6);
1070  ptl.Remove (t5);
1071 
1072  PacketTagList mrg = ptl; // merged list
1073  ATestTag<8> m5 (1);
1074  mrg.Add (m5); // ptl and mrg differ
1075  ptl.Add (t5);
1076  ptl.Add (t6);
1077  ptl.Add (t7);
1078 
1079  CheckRefList (ref, "post merge, orig");
1080  CheckRefList (ptl, "post merge, long chain");
1081  const char * msg = "post merge, short chain";
1082  CheckRef (mrg, t1, msg, false);
1083  CheckRef (mrg, t2, msg, false);
1084  CheckRef (mrg, t3, msg, false);
1085  CheckRef (mrg, t4, msg, false);
1086  CheckRef (mrg, m5, msg, false);
1087  }
1088 # undef RemoveCheck
1089  } // Removal
1090 
1091  { // Replace
1092 
1093  std::cout << GetName () << "check replacing each tag" << std::endl;
1094 
1095 # define ReplaceCheck(n) \
1096  t ## n .m_data = 2; \
1097  { PacketTagList p ## n = ref; \
1098  p ## n .Replace ( t ## n ); \
1099  CheckRefList (ref, "replace " #n " orig"); \
1100  CheckRef (p ## n, t ## n, "replace " #n " copy"); \
1101  }
1102 
1103  ReplaceCheck (1);
1104  ReplaceCheck (2);
1105  ReplaceCheck (3);
1106  ReplaceCheck (4);
1107  ReplaceCheck (5);
1108  ReplaceCheck (6);
1109  ReplaceCheck (7);
1110  }
1111 
1112  { // Timing
1113  std::cout << GetName () << "add+remove timing" << std::endl;
1114  int flm = std::numeric_limits<int>::max ();
1115  const int nIterations = 100;
1116  for (int i = 0; i < nIterations; ++i) {
1117  int now = AddRemoveTime ();
1118  if (now < flm) flm = now;
1119  }
1120  std::cout << GetName () << "min add+remove time: "
1121  << std::setw (8) << flm << " ticks"
1122  << std::endl;
1123 
1124  std::cout << GetName () << "remove timing" << std::endl;
1125  // tags numbered from 1, so add one for (unused) entry at 0
1126  std::vector <int> rmn (tagLast + 1, std::numeric_limits<int>::max ());
1127  for (int i = 0; i < nIterations; ++i) {
1128  for (int j = 1; j <= tagLast; ++j) {
1129  int now = 0;
1130  switch (j) {
1131  case 7: now = RemoveTime (ref, t7); break;
1132  case 6: now = RemoveTime (ref, t6); break;
1133  case 5: now = RemoveTime (ref, t5); break;
1134  case 4: now = RemoveTime (ref, t4); break;
1135  case 3: now = RemoveTime (ref, t3); break;
1136  case 2: now = RemoveTime (ref, t2); break;
1137  case 1: now = RemoveTime (ref, t1); break;
1138  } // switch
1139 
1140  if (now < rmn[j]) rmn[j] = now;
1141  } // for tag j
1142  } // for iteration i
1143  for (int j = tagLast; j > 0; --j) {
1144  std::cout << GetName () << "min remove time: t"
1145  << j << ": "
1146  << std::setw (8) << rmn[j] << " ticks"
1147  << std::endl;
1148  }
1149  } // Timing
1150 
1151 }
1152 
1160 {
1161 public:
1162  PacketTestSuite ();
1163 };
1164 
1166  : TestSuite ("packet", UNIT)
1167 {
1168  AddTestCase (new PacketTest, TestCase::QUICK);
1169  AddTestCase (new PacketTagListTest, TestCase::QUICK);
1170 }
1171 
Protocol header serialization and deserialization.
Definition: header.h:42
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
static TypeId GetTypeId(void)
Register this type.
virtual void DoRun(void)
Implementation to actually run this TestCase.
bool Remove(Tag &tag)
Remove (the first instance of) tag from the list.
Callback< ObjectBase * > GetConstructor(void) const
Get the constructor callback.
Definition: type-id.cc:1061
TypeId GetTypeId(void) const
Definition: packet.cc:34
std::string GetName(void) const
Get the name.
Definition: type-id.cc:977
Packet Tag list unit tests.
TypeId AddConstructor(void)
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:638
void CheckRefList(const PacketTagList &ref, const char *msg, int miss=0)
Checks against a reference PacketTagList.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
bool HasNext(void) const
Definition: packet.cc:65
static TypeId GetTypeId(void)
Register this type.
virtual uint32_t Deserialize(Buffer::Iterator iter)
uint32_t GetSerializedSize(void) const
Returns number of bytes required for packet serialization.
Definition: packet.cc:585
A suite of tests to run.
Definition: test.h:1343
def start()
Definition: core.py:1855
List of the packet tags stored in a packet.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
uint32_t GetStart(void) const
The index is an offset from the start of the packet.
Definition: packet.cc:39
#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:283
Packet unit tests.
encapsulates test code
Definition: test.h:1153
static TypeId GetTypeId(void)
Register this type.
Expected(uint32_t n_, uint32_t start_, uint32_t end_)
Constructor.
network packets
Definition: packet.h:231
TAG_BUFFER_INLINE uint8_t ReadU8(void)
Definition: tag-buffer.h:195
iterator in a Buffer instance
Definition: buffer.h:98
#define MAKE_TEST_TAGS
static TypeId GetTypeId(void)
Register this type.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
void RemoveAllPacketTags(void)
Remove all packet tags.
Definition: packet.cc:984
Identifies a byte tag and a set of bytes within a packet to which the tag applies.
Definition: packet.h:61
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:362
#define max(a, b)
Definition: 80211b.c:43
#define E_DATA(name, start, end, data)
void Prev(void)
go backward by one byte
Definition: buffer.h:851
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
#define CHECK_DATA(p, n,...)
uint8_t data[writeSize]
void DoRun(void)
Implementation to actually run this TestCase.
void AddPaddingAtEnd(uint32_t size)
Add a zero-filled padding to the packet.
Definition: packet.cc:347
static TypeId GetTypeId(void)
Register this type.
Item Next(void)
Definition: packet.cc:70
TypeId SetGroupName(std::string groupName)
Set the group name.
Definition: type-id.cc:930
Protocol trailer serialization and deserialization.
Definition: trailer.h:40
tag a set of bytes in a packet
Definition: tag.h:36
Every class exported by the ns3 library is enclosed in the ns3 namespace.
int RemoveTime(const PacketTagList &ref, ATestTagBase &t, const char *msg=0)
Prints the remove time.
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Definition: packet.cc:307
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:355
Iterator over the set of byte tags in a packet.
Definition: packet.h:54
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:318
bool Peek(Tag &tag) const
Find a tag and return its value.
#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:737
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:172
#define NS_TEST_EXPECT_MSG_EQ_INTERNAL(actual, limit, msg, file, line)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:236
void Add(Tag const &tag) const
Add a tag to the head of this branch.
#define LARGE_TAG_BUFFER_SIZE
void CheckRef(const PacketTagList &ref, ATestTagBase &t, const char *msg, bool miss=false)
Checks against a reference PacketTagList.
virtual void Serialize(Buffer::Iterator iter) const
void DoCheckData(Ptr< const Packet > p, const char *file, int line, uint32_t n,...)
uint32_t GetEnd(void) const
The index is an offset from the start of the packet.
Definition: packet.cc:44
std::string GetName(void) const
Definition: test.cc:370
read and write tag data
Definition: tag-buffer.h:51
void WriteU8(uint8_t data)
Definition: buffer.h:869
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
#define E(name, start, end)
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
#define ReplaceCheck(n)
static PacketTestSuite g_packetTestSuite
Static variable for test initialization.
virtual void Serialize(Buffer::Iterator iter) const
virtual uint32_t Deserialize(Buffer::Iterator iter)
Packet TestSuite.
uint8_t ReadU8(void)
Definition: buffer.h:1021
#define RemoveCheck(n)
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:978
void GetTag(Tag &tag) const
Read the requested tag and store it in the user-provided tag instance.
Definition: packet.cc:49
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
void DoCheck(Ptr< const Packet > p, const char *file, int line, uint32_t n,...)
Checks the packet.
Struct to hold the expected data in the packet.
Expected(uint32_t n_, uint32_t start_, uint32_t end_, uint8_t data_)
Constructor
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:912
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
ByteTagIterator GetByteTagIterator(void) const
Returns an iterator over the set of byte tags included in this packet.
Definition: packet.cc:933
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Serialize a packet, tags, and metadata into a byte buffer.
Definition: packet.cc:638
bool verbose
TypeId HideFromDocumentation(void)
Hide this TypeId from documentation.
Definition: type-id.cc:1128
#define CHECK(p, n,...)
int AddRemoveTime(const bool verbose=false)
Prints the remove time.