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, ...);
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 
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,...)
Checks the packet and its data.
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.