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 ())
98  .SetGroupName ("Network")
99  .HideFromDocumentation ()
100  .AddConstructor<ATestTag<N> > ()
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 ())
256  .SetGroupName ("Network")
257  .HideFromDocumentation ()
258  .AddConstructor<ATestHeader<N> > ()
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 ())
342  .SetGroupName ("Network")
343  .HideFromDocumentation ()
344  .AddConstructor<ATestTrailer<N> > ()
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, ...);
460  void DoCheckData (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
461 };
462 
463 
465  : TestCase ("Packet") {
466 }
467 
468 void
469 PacketTest::DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
470 {
471  std::vector<struct Expected> expected;
472  va_list ap;
473  va_start (ap, n);
474  for (uint32_t k = 0; k < n; ++k)
475  {
476  uint32_t N = va_arg (ap, uint32_t);
477  uint32_t start = va_arg (ap, uint32_t);
478  uint32_t end = va_arg (ap, uint32_t);
479  expected.push_back (Expected (N, start, end));
480  }
481  va_end (ap);
482 
484  uint32_t j = 0;
485  while (i.HasNext () && j < expected.size ())
486  {
487  ByteTagIterator::Item item = i.Next ();
488  struct Expected e = expected[j];
489  std::ostringstream oss;
490  oss << "anon::ATestTag<" << e.n << ">";
491  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetTypeId ().GetName (), oss.str (), "trivial", file, line);
492  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetStart (), e.start, "trivial", file, line);
493  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetEnd (), e.end, "trivial", file, line);
494  ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
495  NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
496  item.GetTag (*tag);
497  NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
498  delete tag;
499  j++;
500  }
501  NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
502  NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
503 }
504 
505 void
506 PacketTest::DoCheckData (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
507 {
508  std::vector<struct Expected> expected;
509  va_list ap;
510  va_start (ap, n);
511  for (uint32_t k = 0; k < n; ++k)
512  {
513  uint32_t N = va_arg (ap, uint32_t);
514  uint32_t start = va_arg (ap, uint32_t);
515  uint32_t end = va_arg (ap, uint32_t);
516  int data = va_arg (ap, int);
517  expected.push_back (Expected (N, start, end, data));
518  }
519  va_end (ap);
520 
522  uint32_t j = 0;
523  while (i.HasNext () && j < expected.size ())
524  {
525  ByteTagIterator::Item item = i.Next ();
526  struct Expected e = expected[j];
527  std::ostringstream oss;
528  oss << "anon::ATestTag<" << e.n << ">";
529  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetTypeId ().GetName (), oss.str (), "trivial", file, line);
530  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetStart (), e.start, "trivial", file, line);
531  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetEnd (), e.end, "trivial", file, line);
532  ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
533  NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
534  item.GetTag (*tag);
535  NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
536  NS_TEST_EXPECT_MSG_EQ (tag->GetData (), e.data, "trivial");
537  delete tag;
538  j++;
539  }
540  NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
541  NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
542 }
543 
544 void
546 {
547  Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
548  Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
549  Ptr<Packet> packet = Create<Packet> ();
550  packet->AddAtEnd (pkt1);
551  packet->AddAtEnd (pkt2);
552 
553  NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 11, "trivial");
554 
555  uint8_t *buf = new uint8_t[packet->GetSize ()];
556  packet->CopyData (buf, packet->GetSize ());
557 
558  std::string msg = std::string (reinterpret_cast<const char *>(buf),
559  packet->GetSize ());
560  delete [] buf;
561 
562  NS_TEST_EXPECT_MSG_EQ (msg, "hello world", "trivial");
563 
564 
565  Ptr<const Packet> p = Create<Packet> (1000);
566 
567  p->AddByteTag (ATestTag<1> ());
568  CHECK (p, 1, E (1, 0, 1000));
569  Ptr<const Packet> copy = p->Copy ();
570  CHECK (copy, 1, E (1, 0, 1000));
571 
572  p->AddByteTag (ATestTag<2> ());
573  CHECK (p, 2, E (1, 0, 1000), E (2, 0, 1000));
574  CHECK (copy, 1, E (1, 0, 1000));
575 
576  {
577  Packet c0 = *copy;
578  Packet c1 = *copy;
579  c0 = c1;
580  CHECK (&c0, 1, E (1, 0, 1000));
581  CHECK (&c1, 1, E (1, 0, 1000));
582  CHECK (copy, 1, E (1, 0, 1000));
583  c0.AddByteTag (ATestTag<10> ());
584  CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
585  CHECK (&c1, 1, E (1, 0, 1000));
586  CHECK (copy, 1, E (1, 0, 1000));
587  }
588 
589  Ptr<Packet> frag0 = p->CreateFragment (0, 10);
590  Ptr<Packet> frag1 = p->CreateFragment (10, 90);
591  Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
592  frag0->AddByteTag (ATestTag<3> ());
593  CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
594  frag1->AddByteTag (ATestTag<4> ());
595  CHECK (frag1, 3, E (1, 0, 90), E (2, 0, 90), E (4, 0, 90));
596  frag2->AddByteTag (ATestTag<5> ());
597  CHECK (frag2, 3, E (1, 0, 900), E (2, 0, 900), E (5, 0, 900));
598 
599  frag1->AddAtEnd (frag2);
600  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));
601 
602  CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
603  frag0->AddAtEnd (frag1);
604  CHECK (frag0, 9,
605  E (1, 0, 10), E (2, 0, 10), E (3, 0, 10),
606  E (1, 10, 100), E (2, 10, 100), E (4, 10, 100),
607  E (1, 100, 1000), E (2, 100, 1000), E (5, 100, 1000));
608 
609 
610  // force caching a buffer of the right size.
611  frag0 = Create<Packet> (1000);
612  frag0->AddHeader (ATestHeader<10> ());
613  frag0 = 0;
614 
615  p = Create<Packet> (1000);
616  p->AddByteTag (ATestTag<20> ());
617  CHECK (p, 1, E (20, 0, 1000));
618  frag0 = p->CreateFragment (10, 90);
619  CHECK (p, 1, E (20, 0, 1000));
620  CHECK (frag0, 1, E (20, 0, 90));
621  p = 0;
622  frag0->AddHeader (ATestHeader<10> ());
623  CHECK (frag0, 1, E (20, 10, 100));
624 
625  {
626  Ptr<Packet> tmp = Create<Packet> (100);
627  tmp->AddByteTag (ATestTag<20> ());
628  CHECK (tmp, 1, E (20, 0, 100));
629  tmp->AddHeader (ATestHeader<10> ());
630  CHECK (tmp, 1, E (20, 10, 110));
631  ATestHeader<10> h;
632  tmp->RemoveHeader (h);
633  CHECK (tmp, 1, E (20, 0, 100));
634  tmp->AddHeader (ATestHeader<10> ());
635  CHECK (tmp, 1, E (20, 10, 110));
636 
637  tmp = Create<Packet> (100);
638  tmp->AddByteTag (ATestTag<20> ());
639  CHECK (tmp, 1, E (20, 0, 100));
640  tmp->AddTrailer (ATestTrailer<10> ());
641  CHECK (tmp, 1, E (20, 0, 100));
642  ATestTrailer<10> t;
643  tmp->RemoveTrailer (t);
644  CHECK (tmp, 1, E (20, 0, 100));
645  tmp->AddTrailer (ATestTrailer<10> ());
646  CHECK (tmp, 1, E (20, 0, 100));
647 
648  }
649 
650  {
651  Ptr<Packet> tmp = Create<Packet> (0);
652  tmp->AddHeader (ATestHeader<156> ());
653  tmp->AddByteTag (ATestTag<20> ());
654  CHECK (tmp, 1, E (20, 0, 156));
655  tmp->RemoveAtStart (120);
656  CHECK (tmp, 1, E (20, 0, 36));
657  Ptr<Packet> a = Create<Packet> (0);
658  a->AddAtEnd (tmp);
659  CHECK (a, 1, E (20, 0, 36));
660  }
661 
662  {
663  Ptr<Packet> tmp = Create<Packet> (0);
664  tmp->AddByteTag (ATestTag<20> ());
665  CHECK (tmp, 0, E (20, 0, 0));
666  }
667  {
668  Ptr<Packet> tmp = Create<Packet> (1000);
669  tmp->AddByteTag (ATestTag<20> ());
670  CHECK (tmp, 1, E (20, 0, 1000));
671  tmp->RemoveAtStart (1000);
672  CHECK (tmp, 0, E (0,0,0));
673  Ptr<Packet> a = Create<Packet> (10);
674  a->AddByteTag (ATestTag<10> ());
675  CHECK (a, 1, E (10, 0, 10));
676  tmp->AddAtEnd (a);
677  CHECK (tmp, 1, E (10, 0, 10));
678  }
679 
680  {
681  Packet p;
682  ATestTag<10> a;
683  p.AddPacketTag (a);
684  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
685  ATestTag<11> b;
686  p.AddPacketTag (b);
687  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
688  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
689  Packet copy = p;
690  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
691  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
692  ATestTag<12> c;
693  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), false, "trivial");
694  copy.AddPacketTag (c);
695  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
696  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
697  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
698  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
699  copy.RemovePacketTag (b);
700  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), false, "trivial");
701  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
702  p.RemovePacketTag (a);
703  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), false, "trivial");
704  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
705  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
706  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
707  p.RemoveAllPacketTags ();
708  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), false, "trivial");
709  }
710 
711  /* Test Serialization and Deserialization of Packet with PacketTag data */
712  {
713  Ptr<Packet> p1 = Create<Packet> (1000);;
714  ATestTag<10> a1(65);
715  ATestTag<11> b1(66);
716  ATestTag<12> c1(67);
717 
718  p1->AddPacketTag (a1);
719  p1->AddPacketTag (b1);
720  p1->AddPacketTag (c1);
721 
722  uint32_t serializedSize = p1->GetSerializedSize ();
723  uint8_t* buffer = new uint8_t[serializedSize + 16];
724  p1->Serialize (buffer, serializedSize);
725 
726  Ptr<Packet> p2 = Create<Packet> (buffer, serializedSize, true);
727 
728  delete [] buffer;
729 
730  ATestTag<10> a2;
731  ATestTag<11> b2;
732  ATestTag<12> c2;
733 
734  NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(a2), true, "trivial");
735  NS_TEST_EXPECT_MSG_EQ (a2.GetData (), 65, "trivial");
736  NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(b2), true, "trivial");
737  NS_TEST_EXPECT_MSG_EQ (b2.GetData (), 66, "trivial");
738  NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(c2), true, "trivial");
739  NS_TEST_EXPECT_MSG_EQ (c2.GetData (), 67, "trivial");
740  }
741 
742  /* Test Serialization and Deserialization of Packet with ByteTag data */
743  {
744  Ptr<Packet> p1 = Create<Packet> (1000);;
745 
746  ATestTag<10> a1(65);
747  ATestTag<11> b1(66);
748  ATestTag<12> c1(67);
749 
750  p1->AddByteTag (a1);
751  p1->AddByteTag (b1);
752  p1->AddByteTag (c1);
753 
754  CHECK (p1, 3, E (10, 0, 1000), E (11, 0, 1000), E (12, 0, 1000));
755 
756  uint32_t serializedSize = p1->GetSerializedSize ();
757  uint8_t* buffer = new uint8_t[serializedSize];
758  p1->Serialize (buffer, serializedSize);
759 
760  Ptr<Packet> p2 = Create<Packet> (buffer, serializedSize, true);
761 
762  delete [] buffer;
763 
764  CHECK_DATA (p2, 3, E_DATA (10, 0, 1000, 65), E_DATA (11, 0, 1000, 66), E_DATA (12, 0, 1000, 67));
765  }
766 
767  {
770  Ptr<Packet> tmp = Create<Packet> (1000);
771  tmp->AddByteTag (ATestTag<20> ());
772  CHECK (tmp, 1, E (20, 0, 1000));
773  tmp->AddHeader (ATestHeader<2> ());
774  CHECK (tmp, 1, E (20, 2, 1002));
775  tmp->RemoveAtStart (1);
776  CHECK (tmp, 1, E (20, 1, 1001));
777 #if 0
778  tmp->PeekData ();
779  CHECK (tmp, 1, E (20, 1, 1001));
780 #endif
781  }
782 
783  /* Test reducing tagged packet size and increasing it back. */
784  {
785  Ptr<Packet> tmp = Create<Packet> (0);
786  tmp->AddHeader (ATestHeader<100> ());
787  tmp->AddByteTag (ATestTag<25> ());
788  CHECK (tmp, 1, E (25, 0, 100));
789  tmp->RemoveAtStart (50);
790  CHECK (tmp, 1, E (25, 0, 50));
791  tmp->AddHeader (ATestHeader<50> ());
792  CHECK (tmp, 1, E (25, 50, 100));
793  }
794 
795  /* Similar test case, but using trailer instead of header. */
796  {
797  Ptr<Packet> tmp = Create<Packet> (0);
798  tmp->AddTrailer (ATestTrailer<100> ());
799  tmp->AddByteTag (ATestTag<25> ());
800  CHECK (tmp, 1, E (25, 0, 100));
801  tmp->RemoveAtEnd (50);
802  CHECK (tmp, 1, E (25, 0, 50));
803  tmp->AddTrailer (ATestTrailer<50> ());
804  CHECK (tmp, 1, E (25, 0, 50));
805  }
806 
807  /* Test reducing tagged packet size and increasing it by half. */
808  {
809  Ptr<Packet> tmp = Create<Packet> (0);
810  tmp->AddHeader (ATestHeader<100> ());
811  tmp->AddByteTag (ATestTag<25> ());
812  CHECK (tmp, 1, E (25, 0, 100));
813  tmp->RemoveAtStart (50);
814  CHECK (tmp, 1, E (25, 0, 50));
815  tmp->AddHeader (ATestHeader<25> ());
816  CHECK (tmp, 1, E (25, 25, 75));
817  }
818 
819  /* Similar test case, but using trailer instead of header. */
820  {
821  Ptr<Packet> tmp = Create<Packet> (0);
822  tmp->AddTrailer (ATestTrailer<100> ());
823  tmp->AddByteTag (ATestTag<25> ());
824  CHECK (tmp, 1, E (25, 0, 100));
825  tmp->RemoveAtEnd (50);
826  CHECK (tmp, 1, E (25, 0, 50));
827  tmp->AddTrailer (ATestTrailer<25> ());
828  CHECK (tmp, 1, E (25, 0, 50));
829  }
830 
831  /* Test AddPaddingAtEnd. */
832  {
833  Ptr<Packet> tmp = Create<Packet> (0);
834  tmp->AddTrailer (ATestTrailer<100> ());
835  tmp->AddByteTag (ATestTag<25> ());
836  CHECK (tmp, 1, E (25, 0, 100));
837  tmp->RemoveAtEnd (50);
838  CHECK (tmp, 1, E (25, 0, 50));
839  tmp->AddPaddingAtEnd (50);
840  CHECK (tmp, 1, E (25, 0, 50));
841  }
842 
843  /* Test reducing tagged packet size and increasing it back,
844  * now using padding bytes to avoid triggering dirty state
845  * in virtual buffer
846  */
847  {
848  Ptr<Packet> tmp = Create<Packet> (100);
849  tmp->AddByteTag (ATestTag<25> ());
850  CHECK (tmp, 1, E (25, 0, 100));
851  tmp->RemoveAtEnd (50);
852  CHECK (tmp, 1, E (25, 0, 50));
853  tmp->AddPaddingAtEnd (50);
854  CHECK (tmp, 1, E (25, 0, 50));
855  }
856 
857  /* Test ALargeTestTag */
858  {
859  Ptr<Packet> tmp = Create<Packet> (0);
860  ALargeTestTag a;
861  tmp->AddPacketTag (a);
862  }
863 }
864 
872 {
873 public:
875  virtual ~PacketTagListTest ();
876 private:
877  void DoRun (void);
885  void CheckRef (const PacketTagList & ref,
886  ATestTagBase & t,
887  const char * msg,
888  bool miss = false);
895  void CheckRefList (const PacketTagList & ref,
896  const char * msg,
897  int miss = 0);
898 
906  int RemoveTime (const PacketTagList & ref,
907  ATestTagBase & t,
908  const char * msg = 0);
909 
915  int AddRemoveTime (const bool verbose = false);
916 };
917 
919  : TestCase ("PacketTagListTest: ")
920 {
921 }
922 
924 {
925 }
926 
927 void
929  ATestTagBase & t,
930  const char * msg,
931  bool miss)
932 {
933  int expect = t.GetData (); // the value we should find
934  bool found = ref.Peek (t); // rewrites t with actual value
935  NS_TEST_EXPECT_MSG_EQ (found, !miss,
936  msg << ": ref contains "
937  << t.GetTypeId ().GetName ());
938  if (found) {
939  NS_TEST_EXPECT_MSG_EQ (t.GetData (), expect,
940  msg << ": ref " << t.GetTypeId ().GetName ()
941  << " = " << expect);
942  }
943 }
944 
945  // A set of tags with data value 1, to check COW
946 #define MAKE_TEST_TAGS \
947  ATestTag<1> t1 (1); \
948  ATestTag<2> t2 (1); \
949  ATestTag<3> t3 (1); \
950  ATestTag<4> t4 (1); \
951  ATestTag<5> t5 (1); \
952  ATestTag<6> t6 (1); \
953  ATestTag<7> t7 (1); \
954  const int tagLast = 7; /* length of ref PacketTagList */ \
955  NS_UNUSED (tagLast) /* silence warnings */
956 
957 
958 
959 void
961  const char * msg,
962  int miss /* = 0 */)
963 {
965  CheckRef (ptl, t1, msg, miss == 1);
966  CheckRef (ptl, t2, msg, miss == 2);
967  CheckRef (ptl, t3, msg, miss == 3);
968  CheckRef (ptl, t4, msg, miss == 4);
969  CheckRef (ptl, t5, msg, miss == 5);
970  CheckRef (ptl, t6, msg, miss == 6);
971  CheckRef (ptl, t7, msg, miss == 7);
972 }
973 
974 int
976  ATestTagBase & t,
977  const char * msg /* = 0 */)
978 {
979  const int reps = 10000;
980  std::vector< PacketTagList > ptv(reps, ref);
981  int start = clock ();
982  for (int i = 0; i < reps; ++i) {
983  ptv[i].Remove (t);
984  }
985  int stop = clock ();
986  int delta = stop - start;
987  if (msg) {
988  std::cout << GetName () << "remove time: " << msg << ": " << std::setw (8)
989  << delta << " ticks to remove "
990  << reps << " times"
991  << std::endl;
992  }
993  return delta;
994 }
995 
996 int
997 PacketTagListTest::AddRemoveTime (const bool verbose /* = false */)
998 {
999  const int reps = 100000;
1000  PacketTagList ptl;
1001  ATestTag <2> t(2);
1002  int start = clock ();
1003  for (int i = 0; i < reps; ++i) {
1004  ptl.Add (t);
1005  ptl.Remove (t);
1006  }
1007  int stop = clock ();
1008  int delta = stop - start;
1009  if (verbose) {
1010  std::cout << GetName () << "add/remove time: " << std::setw (8)
1011  << delta << " ticks to add+remove "
1012  << reps << " times"
1013  << std::endl;
1014  }
1015  return delta;
1016 }
1017 
1018 void
1020 {
1021  std::cout << GetName () << "begin" << std::endl;
1022 
1023  MAKE_TEST_TAGS ;
1024 
1025  PacketTagList ref; // empty list
1026  ref.Add (t1); // last
1027  ref.Add (t2); // post merge
1028  ref.Add (t3); // merge successor
1029  ref.Add (t4); // merge
1030  ref.Add (t5); // merge precursor
1031  ref.Add (t6); // pre-merge
1032  ref.Add (t7); // first
1033 
1034  { // Peek
1035  std::cout << GetName () << "check Peek (missing tag) returns false"
1036  << std::endl;
1037  ATestTag<10> t10;
1038  NS_TEST_EXPECT_MSG_EQ (ref.Peek (t10), false, "missing tag");
1039  }
1040 
1041  { // Copy ctor, assignment
1042  std::cout << GetName () << "check copy and assignment" << std::endl;
1043  { PacketTagList ptl (ref);
1044  CheckRefList (ref, "copy ctor orig");
1045  CheckRefList (ptl, "copy ctor copy");
1046  }
1047  { PacketTagList ptl = ref;
1048  CheckRefList (ref, "assignment orig");
1049  CheckRefList (ptl, "assignment copy");
1050  }
1051  }
1052 
1053  { // Removal
1054 # define RemoveCheck(n) \
1055  { PacketTagList p ## n = ref; \
1056  p ## n .Remove ( t ## n ); \
1057  CheckRefList (ref, "remove " #n " orig"); \
1058  CheckRefList (p ## n, "remove " #n " copy", n); \
1059  }
1060 
1061  { // Remove single tags from list
1062  std::cout << GetName () << "check removal of each tag" << std::endl;
1063  RemoveCheck (1);
1064  RemoveCheck (2);
1065  RemoveCheck (3);
1066  RemoveCheck (4);
1067  RemoveCheck (5);
1068  RemoveCheck (6);
1069  RemoveCheck (7);
1070  }
1071 
1072  { // Remove in the presence of a merge
1073  std::cout << GetName () << "check removal doesn't disturb merge "
1074  << std::endl;
1075  PacketTagList ptl = ref;
1076  ptl.Remove (t7);
1077  ptl.Remove (t6);
1078  ptl.Remove (t5);
1079 
1080  PacketTagList mrg = ptl; // merged list
1081  ATestTag<8> m5 (1);
1082  mrg.Add (m5); // ptl and mrg differ
1083  ptl.Add (t5);
1084  ptl.Add (t6);
1085  ptl.Add (t7);
1086 
1087  CheckRefList (ref, "post merge, orig");
1088  CheckRefList (ptl, "post merge, long chain");
1089  const char * msg = "post merge, short chain";
1090  CheckRef (mrg, t1, msg, false);
1091  CheckRef (mrg, t2, msg, false);
1092  CheckRef (mrg, t3, msg, false);
1093  CheckRef (mrg, t4, msg, false);
1094  CheckRef (mrg, m5, msg, false);
1095  }
1096 # undef RemoveCheck
1097  } // Removal
1098 
1099  { // Replace
1100 
1101  std::cout << GetName () << "check replacing each tag" << std::endl;
1102 
1103 # define ReplaceCheck(n) \
1104  t ## n .m_data = 2; \
1105  { PacketTagList p ## n = ref; \
1106  p ## n .Replace ( t ## n ); \
1107  CheckRefList (ref, "replace " #n " orig"); \
1108  CheckRef (p ## n, t ## n, "replace " #n " copy"); \
1109  }
1110 
1111  ReplaceCheck (1);
1112  ReplaceCheck (2);
1113  ReplaceCheck (3);
1114  ReplaceCheck (4);
1115  ReplaceCheck (5);
1116  ReplaceCheck (6);
1117  ReplaceCheck (7);
1118  }
1119 
1120  { // Timing
1121  std::cout << GetName () << "add+remove timing" << std::endl;
1122  int flm = std::numeric_limits<int>::max ();
1123  const int nIterations = 100;
1124  for (int i = 0; i < nIterations; ++i) {
1125  int now = AddRemoveTime ();
1126  if (now < flm) flm = now;
1127  }
1128  std::cout << GetName () << "min add+remove time: "
1129  << std::setw (8) << flm << " ticks"
1130  << std::endl;
1131 
1132  std::cout << GetName () << "remove timing" << std::endl;
1133  // tags numbered from 1, so add one for (unused) entry at 0
1134  std::vector <int> rmn (tagLast + 1, std::numeric_limits<int>::max ());
1135  for (int i = 0; i < nIterations; ++i) {
1136  for (int j = 1; j <= tagLast; ++j) {
1137  int now = 0;
1138  switch (j) {
1139  case 7: now = RemoveTime (ref, t7); break;
1140  case 6: now = RemoveTime (ref, t6); break;
1141  case 5: now = RemoveTime (ref, t5); break;
1142  case 4: now = RemoveTime (ref, t4); break;
1143  case 3: now = RemoveTime (ref, t3); break;
1144  case 2: now = RemoveTime (ref, t2); break;
1145  case 1: now = RemoveTime (ref, t1); break;
1146  } // switch
1147 
1148  if (now < rmn[j]) rmn[j] = now;
1149  } // for tag j
1150  } // for iteration i
1151  for (int j = tagLast; j > 0; --j) {
1152  std::cout << GetName () << "min remove time: t"
1153  << j << ": "
1154  << std::setw (8) << rmn[j] << " ticks"
1155  << std::endl;
1156  }
1157  } // Timing
1158 
1159 }
1160 
1168 {
1169 public:
1170  PacketTestSuite ();
1171 };
1172 
1174  : TestSuite ("packet", UNIT)
1175 {
1176  AddTestCase (new PacketTest, TestCase::QUICK);
1177  AddTestCase (new PacketTagListTest, TestCase::QUICK);
1178 }
1179 
#define max(a, b)
Definition: 80211b.c:43
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 CheckRef(const PacketTagList &ref, ATestTagBase &t, const char *msg, bool miss=false)
Checks against a reference PacketTagList.
void DoRun(void)
Implementation to actually run this TestCase.
int RemoveTime(const PacketTagList &ref, ATestTagBase &t, const char *msg=0)
Prints the remove time.
Packet unit tests.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void DoCheckData(Ptr< const Packet > p, const char *file, int line, uint32_t n,...)
Checks the packet and its data.
void DoCheck(Ptr< const Packet > p, const char *file, int line, uint32_t n,...)
Checks the packet.
Packet TestSuite.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
static TypeId GetTypeId(void)
Register this type.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
virtual uint32_t Deserialize(Buffer::Iterator iter)
virtual void Serialize(Buffer::Iterator iter) const
static TypeId GetTypeId(void)
Register this type.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
static TypeId GetTypeId(void)
Register this type.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
virtual void Serialize(Buffer::Iterator iter) const
virtual uint32_t Deserialize(Buffer::Iterator iter)
static TypeId GetTypeId(void)
Register this type.
iterator in a Buffer instance
Definition: buffer.h:99
void WriteU8(uint8_t data)
Definition: buffer.h:869
uint8_t ReadU8(void)
Definition: buffer.h:1021
void Prev(void)
go backward by one byte
Definition: buffer.h:851
Identifies a byte tag and a set of bytes within a packet to which the tag applies.
Definition: packet.h:62
uint32_t GetEnd(void) const
The index is an offset from the start of the packet.
Definition: packet.cc:44
TypeId GetTypeId(void) const
Definition: packet.cc:34
void GetTag(Tag &tag) const
Read the requested tag and store it in the user-provided tag instance.
Definition: packet.cc:49
uint32_t GetStart(void) const
The index is an offset from the start of the packet.
Definition: packet.cc:39
Iterator over the set of byte tags in a packet.
Definition: packet.h:55
bool HasNext(void) const
Definition: packet.cc:65
Item Next(void)
Definition: packet.cc:70
Protocol header serialization and deserialization.
Definition: header.h:43
network packets
Definition: packet.h:232
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:318
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:355
void RemoveAllPacketTags(void)
Remove all packet tags.
Definition: packet.cc:984
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:362
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Serialize a packet, tags, and metadata into a byte buffer.
Definition: packet.cc:638
ByteTagIterator GetByteTagIterator(void) const
Returns an iterator over the set of byte tags included in this packet.
Definition: packet.cc:933
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
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
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:912
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Definition: packet.cc:307
void AddPaddingAtEnd(uint32_t size)
Add a zero-filled padding to the packet.
Definition: packet.cc:347
uint32_t GetSerializedSize(void) const
Returns number of bytes required for packet serialization.
Definition: packet.cc:585
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:978
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
List of the packet tags stored in a packet.
bool Remove(Tag &tag)
Remove (the first instance of) tag from the list.
bool Peek(Tag &tag) const
Find a tag and return its value.
void Add(Tag const &tag) const
Add a tag to the head of this branch.
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(void)
Definition: tag-buffer.h:195
tag a set of bytes in a packet
Definition: tag.h:37
encapsulates test code
Definition: test.h:1154
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
std::string GetName(void) const
Definition: test.cc:370
A suite of tests to run.
Definition: test.h:1344
Protocol trailer serialization and deserialization.
Definition: trailer.h:41
a unique identifier for an interface.
Definition: type-id.h:59
Callback< ObjectBase * > GetConstructor(void) const
Get the constructor callback.
Definition: type-id.cc:1061
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
std::string GetName(void) const
Get the name.
Definition: type-id.cc:977
#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
#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
#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
Every class exported by the ns3 library is enclosed in the ns3 namespace.
def start()
Definition: core.py:1855
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.