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  ATestTag<10> a2;
721  ATestTag<11> b2;
722  ATestTag<12> c2;
723 
724  NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(a2), true, "trivial");
725  NS_TEST_EXPECT_MSG_EQ (a2.GetData (), 65, "trivial");
726  NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(b2), true, "trivial");
727  NS_TEST_EXPECT_MSG_EQ (b2.GetData (), 66, "trivial");
728  NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(c2), true, "trivial");
729  NS_TEST_EXPECT_MSG_EQ (c2.GetData (), 67, "trivial");
730  }
731 
732  /* Test Serialization and Deserialization of Packet with ByteTag data */
733  {
734  Ptr<Packet> p1 = Create<Packet> (1000);;
735 
736  ATestTag<10> a1(65);
737  ATestTag<11> b1(66);
738  ATestTag<12> c1(67);
739 
740  p1->AddByteTag (a1);
741  p1->AddByteTag (b1);
742  p1->AddByteTag (c1);
743 
744  CHECK (p1, 3, E (10, 0, 1000), E (11, 0, 1000), E (12, 0, 1000));
745 
746  uint32_t serializedSize = p1->GetSerializedSize ();
747  uint8_t* buffer = new uint8_t[serializedSize];
748  p1->Serialize (buffer, serializedSize);
749 
750  Ptr<Packet> p2 = Create<Packet> (buffer, serializedSize, true);
751 
752  CHECK_DATA (p2, 3, E_DATA (10, 0, 1000, 65), E_DATA (11, 0, 1000, 66), E_DATA (12, 0, 1000, 67));
753  }
754 
755  {
758  Ptr<Packet> tmp = Create<Packet> (1000);
759  tmp->AddByteTag (ATestTag<20> ());
760  CHECK (tmp, 1, E (20, 0, 1000));
761  tmp->AddHeader (ATestHeader<2> ());
762  CHECK (tmp, 1, E (20, 2, 1002));
763  tmp->RemoveAtStart (1);
764  CHECK (tmp, 1, E (20, 1, 1001));
765 #if 0
766  tmp->PeekData ();
767  CHECK (tmp, 1, E (20, 1, 1001));
768 #endif
769  }
770 
771  /* Test reducing tagged packet size and increasing it back. */
772  {
773  Ptr<Packet> tmp = Create<Packet> (0);
774  tmp->AddHeader (ATestHeader<100> ());
775  tmp->AddByteTag (ATestTag<25> ());
776  CHECK (tmp, 1, E (25, 0, 100));
777  tmp->RemoveAtStart (50);
778  CHECK (tmp, 1, E (25, 0, 50));
779  tmp->AddHeader (ATestHeader<50> ());
780  CHECK (tmp, 1, E (25, 50, 100));
781  }
782 
783  /* Similar test case, but using trailer instead of header. */
784  {
785  Ptr<Packet> tmp = Create<Packet> (0);
786  tmp->AddTrailer (ATestTrailer<100> ());
787  tmp->AddByteTag (ATestTag<25> ());
788  CHECK (tmp, 1, E (25, 0, 100));
789  tmp->RemoveAtEnd (50);
790  CHECK (tmp, 1, E (25, 0, 50));
791  tmp->AddTrailer (ATestTrailer<50> ());
792  CHECK (tmp, 1, E (25, 0, 50));
793  }
794 
795  /* Test reducing tagged packet size and increasing it by half. */
796  {
797  Ptr<Packet> tmp = Create<Packet> (0);
798  tmp->AddHeader (ATestHeader<100> ());
799  tmp->AddByteTag (ATestTag<25> ());
800  CHECK (tmp, 1, E (25, 0, 100));
801  tmp->RemoveAtStart (50);
802  CHECK (tmp, 1, E (25, 0, 50));
803  tmp->AddHeader (ATestHeader<25> ());
804  CHECK (tmp, 1, E (25, 25, 75));
805  }
806 
807  /* Similar test case, but using trailer instead of header. */
808  {
809  Ptr<Packet> tmp = Create<Packet> (0);
810  tmp->AddTrailer (ATestTrailer<100> ());
811  tmp->AddByteTag (ATestTag<25> ());
812  CHECK (tmp, 1, E (25, 0, 100));
813  tmp->RemoveAtEnd (50);
814  CHECK (tmp, 1, E (25, 0, 50));
815  tmp->AddTrailer (ATestTrailer<25> ());
816  CHECK (tmp, 1, E (25, 0, 50));
817  }
818 
819  /* Test AddPaddingAtEnd. */
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->AddPaddingAtEnd (50);
828  CHECK (tmp, 1, E (25, 0, 50));
829  }
830 
831  /* Test reducing tagged packet size and increasing it back,
832  * now using padding bytes to avoid triggering dirty state
833  * in virtual buffer
834  */
835  {
836  Ptr<Packet> tmp = Create<Packet> (100);
837  tmp->AddByteTag (ATestTag<25> ());
838  CHECK (tmp, 1, E (25, 0, 100));
839  tmp->RemoveAtEnd (50);
840  CHECK (tmp, 1, E (25, 0, 50));
841  tmp->AddPaddingAtEnd (50);
842  CHECK (tmp, 1, E (25, 0, 50));
843  }
844 
845  /* Test ALargeTestTag */
846  {
847  Ptr<Packet> tmp = Create<Packet> (0);
848  ALargeTestTag a;
849  tmp->AddPacketTag (a);
850  }
851 }
852 
860 {
861 public:
863  virtual ~PacketTagListTest ();
864 private:
865  void DoRun (void);
873  void CheckRef (const PacketTagList & ref,
874  ATestTagBase & t,
875  const char * msg,
876  bool miss = false);
883  void CheckRefList (const PacketTagList & ref,
884  const char * msg,
885  int miss = 0);
886 
894  int RemoveTime (const PacketTagList & ref,
895  ATestTagBase & t,
896  const char * msg = 0);
897 
903  int AddRemoveTime (const bool verbose = false);
904 };
905 
907  : TestCase ("PacketTagListTest: ")
908 {
909 }
910 
912 {
913 }
914 
915 void
917  ATestTagBase & t,
918  const char * msg,
919  bool miss)
920 {
921  int expect = t.GetData (); // the value we should find
922  bool found = ref.Peek (t); // rewrites t with actual value
923  NS_TEST_EXPECT_MSG_EQ (found, !miss,
924  msg << ": ref contains "
925  << t.GetTypeId ().GetName ());
926  if (found) {
927  NS_TEST_EXPECT_MSG_EQ (t.GetData (), expect,
928  msg << ": ref " << t.GetTypeId ().GetName ()
929  << " = " << expect);
930  }
931 }
932 
933  // A set of tags with data value 1, to check COW
934 #define MAKE_TEST_TAGS \
935  ATestTag<1> t1 (1); \
936  ATestTag<2> t2 (1); \
937  ATestTag<3> t3 (1); \
938  ATestTag<4> t4 (1); \
939  ATestTag<5> t5 (1); \
940  ATestTag<6> t6 (1); \
941  ATestTag<7> t7 (1); \
942  const int tagLast = 7; /* length of ref PacketTagList */ \
943  NS_UNUSED (tagLast) /* silence warnings */
944 
945 
946 
947 void
949  const char * msg,
950  int miss /* = 0 */)
951 {
953  CheckRef (ptl, t1, msg, miss == 1);
954  CheckRef (ptl, t2, msg, miss == 2);
955  CheckRef (ptl, t3, msg, miss == 3);
956  CheckRef (ptl, t4, msg, miss == 4);
957  CheckRef (ptl, t5, msg, miss == 5);
958  CheckRef (ptl, t6, msg, miss == 6);
959  CheckRef (ptl, t7, msg, miss == 7);
960 }
961 
962 int
964  ATestTagBase & t,
965  const char * msg /* = 0 */)
966 {
967  const int reps = 10000;
968  std::vector< PacketTagList > ptv(reps, ref);
969  int start = clock ();
970  for (int i = 0; i < reps; ++i) {
971  ptv[i].Remove (t);
972  }
973  int stop = clock ();
974  int delta = stop - start;
975  if (msg) {
976  std::cout << GetName () << "remove time: " << msg << ": " << std::setw (8)
977  << delta << " ticks to remove "
978  << reps << " times"
979  << std::endl;
980  }
981  return delta;
982 }
983 
984 int
985 PacketTagListTest::AddRemoveTime (const bool verbose /* = false */)
986 {
987  const int reps = 100000;
988  PacketTagList ptl;
989  ATestTag <2> t(2);
990  int start = clock ();
991  for (int i = 0; i < reps; ++i) {
992  ptl.Add (t);
993  ptl.Remove (t);
994  }
995  int stop = clock ();
996  int delta = stop - start;
997  if (verbose) {
998  std::cout << GetName () << "add/remove time: " << std::setw (8)
999  << delta << " ticks to add+remove "
1000  << reps << " times"
1001  << std::endl;
1002  }
1003  return delta;
1004 }
1005 
1006 void
1008 {
1009  std::cout << GetName () << "begin" << std::endl;
1010 
1011  MAKE_TEST_TAGS ;
1012 
1013  PacketTagList ref; // empty list
1014  ref.Add (t1); // last
1015  ref.Add (t2); // post merge
1016  ref.Add (t3); // merge successor
1017  ref.Add (t4); // merge
1018  ref.Add (t5); // merge precursor
1019  ref.Add (t6); // pre-merge
1020  ref.Add (t7); // first
1021 
1022  { // Peek
1023  std::cout << GetName () << "check Peek (missing tag) returns false"
1024  << std::endl;
1025  ATestTag<10> t10;
1026  NS_TEST_EXPECT_MSG_EQ (ref.Peek (t10), false, "missing tag");
1027  }
1028 
1029  { // Copy ctor, assignment
1030  std::cout << GetName () << "check copy and assignment" << std::endl;
1031  { PacketTagList ptl (ref);
1032  CheckRefList (ref, "copy ctor orig");
1033  CheckRefList (ptl, "copy ctor copy");
1034  }
1035  { PacketTagList ptl = ref;
1036  CheckRefList (ref, "assignment orig");
1037  CheckRefList (ptl, "assignment copy");
1038  }
1039  }
1040 
1041  { // Removal
1042 # define RemoveCheck(n) \
1043  { PacketTagList p ## n = ref; \
1044  p ## n .Remove ( t ## n ); \
1045  CheckRefList (ref, "remove " #n " orig"); \
1046  CheckRefList (p ## n, "remove " #n " copy", n); \
1047  }
1048 
1049  { // Remove single tags from list
1050  std::cout << GetName () << "check removal of each tag" << std::endl;
1051  RemoveCheck (1);
1052  RemoveCheck (2);
1053  RemoveCheck (3);
1054  RemoveCheck (4);
1055  RemoveCheck (5);
1056  RemoveCheck (6);
1057  RemoveCheck (7);
1058  }
1059 
1060  { // Remove in the presence of a merge
1061  std::cout << GetName () << "check removal doesn't disturb merge "
1062  << std::endl;
1063  PacketTagList ptl = ref;
1064  ptl.Remove (t7);
1065  ptl.Remove (t6);
1066  ptl.Remove (t5);
1067 
1068  PacketTagList mrg = ptl; // merged list
1069  ATestTag<8> m5 (1);
1070  mrg.Add (m5); // ptl and mrg differ
1071  ptl.Add (t5);
1072  ptl.Add (t6);
1073  ptl.Add (t7);
1074 
1075  CheckRefList (ref, "post merge, orig");
1076  CheckRefList (ptl, "post merge, long chain");
1077  const char * msg = "post merge, short chain";
1078  CheckRef (mrg, t1, msg, false);
1079  CheckRef (mrg, t2, msg, false);
1080  CheckRef (mrg, t3, msg, false);
1081  CheckRef (mrg, t4, msg, false);
1082  CheckRef (mrg, m5, msg, false);
1083  }
1084 # undef RemoveCheck
1085  } // Removal
1086 
1087  { // Replace
1088 
1089  std::cout << GetName () << "check replacing each tag" << std::endl;
1090 
1091 # define ReplaceCheck(n) \
1092  t ## n .m_data = 2; \
1093  { PacketTagList p ## n = ref; \
1094  p ## n .Replace ( t ## n ); \
1095  CheckRefList (ref, "replace " #n " orig"); \
1096  CheckRef (p ## n, t ## n, "replace " #n " copy"); \
1097  }
1098 
1099  ReplaceCheck (1);
1100  ReplaceCheck (2);
1101  ReplaceCheck (3);
1102  ReplaceCheck (4);
1103  ReplaceCheck (5);
1104  ReplaceCheck (6);
1105  ReplaceCheck (7);
1106  }
1107 
1108  { // Timing
1109  std::cout << GetName () << "add+remove timing" << std::endl;
1110  int flm = std::numeric_limits<int>::max ();
1111  const int nIterations = 100;
1112  for (int i = 0; i < nIterations; ++i) {
1113  int now = AddRemoveTime ();
1114  if (now < flm) flm = now;
1115  }
1116  std::cout << GetName () << "min add+remove time: "
1117  << std::setw (8) << flm << " ticks"
1118  << std::endl;
1119 
1120  std::cout << GetName () << "remove timing" << std::endl;
1121  // tags numbered from 1, so add one for (unused) entry at 0
1122  std::vector <int> rmn (tagLast + 1, std::numeric_limits<int>::max ());
1123  for (int i = 0; i < nIterations; ++i) {
1124  for (int j = 1; j <= tagLast; ++j) {
1125  int now = 0;
1126  switch (j) {
1127  case 7: now = RemoveTime (ref, t7); break;
1128  case 6: now = RemoveTime (ref, t6); break;
1129  case 5: now = RemoveTime (ref, t5); break;
1130  case 4: now = RemoveTime (ref, t4); break;
1131  case 3: now = RemoveTime (ref, t3); break;
1132  case 2: now = RemoveTime (ref, t2); break;
1133  case 1: now = RemoveTime (ref, t1); break;
1134  } // switch
1135 
1136  if (now < rmn[j]) rmn[j] = now;
1137  } // for tag j
1138  } // for iteration i
1139  for (int j = tagLast; j > 0; --j) {
1140  std::cout << GetName () << "min remove time: t"
1141  << j << ": "
1142  << std::setw (8) << rmn[j] << " ticks"
1143  << std::endl;
1144  }
1145  } // Timing
1146 
1147 }
1148 
1156 {
1157 public:
1158  PacketTestSuite ();
1159 };
1160 
1162  : TestSuite ("packet", UNIT)
1163 {
1164  AddTestCase (new PacketTest, TestCase::QUICK);
1165  AddTestCase (new PacketTagListTest, TestCase::QUICK);
1166 }
1167 
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.