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_) {}
398 
399  uint32_t n;
400  uint32_t start;
401  uint32_t end;
402 };
403 
404 }
405 
406 // tag name, start, end
407 #define E(a,b,c) a,b,c
408 
409 #define CHECK(p, n, ...) \
410  DoCheck (p, __FILE__, __LINE__, n, __VA_ARGS__)
411 
418 class PacketTest : public TestCase
419 {
420 public:
421  PacketTest ();
422  virtual void DoRun (void);
423 private:
432  void DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
433 };
434 
435 
437  : TestCase ("Packet") {
438 }
439 
440 void
441 PacketTest::DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
442 {
443  std::vector<struct Expected> expected;
444  va_list ap;
445  va_start (ap, n);
446  for (uint32_t k = 0; k < n; ++k)
447  {
448  uint32_t N = va_arg (ap, uint32_t);
449  uint32_t start = va_arg (ap, uint32_t);
450  uint32_t end = va_arg (ap, uint32_t);
451  expected.push_back (Expected (N, start, end));
452  }
453  va_end (ap);
454 
456  uint32_t j = 0;
457  while (i.HasNext () && j < expected.size ())
458  {
459  ByteTagIterator::Item item = i.Next ();
460  struct Expected e = expected[j];
461  std::ostringstream oss;
462  oss << "anon::ATestTag<" << e.n << ">";
463  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetTypeId ().GetName (), oss.str (), "trivial", file, line);
464  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetStart (), e.start, "trivial", file, line);
465  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetEnd (), e.end, "trivial", file, line);
466  ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
467  NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
468  item.GetTag (*tag);
469  NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
470  delete tag;
471  j++;
472  }
473  NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
474  NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
475 }
476 
477 void
479 {
480  Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
481  Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
482  Ptr<Packet> packet = Create<Packet> ();
483  packet->AddAtEnd (pkt1);
484  packet->AddAtEnd (pkt2);
485 
486  NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 11, "trivial");
487 
488  uint8_t *buf = new uint8_t[packet->GetSize ()];
489  packet->CopyData (buf, packet->GetSize ());
490 
491  std::string msg = std::string (reinterpret_cast<const char *>(buf),
492  packet->GetSize ());
493  delete [] buf;
494 
495  NS_TEST_EXPECT_MSG_EQ (msg, "hello world", "trivial");
496 
497 
498  Ptr<const Packet> p = Create<Packet> (1000);
499 
500  p->AddByteTag (ATestTag<1> ());
501  CHECK (p, 1, E (1, 0, 1000));
502  Ptr<const Packet> copy = p->Copy ();
503  CHECK (copy, 1, E (1, 0, 1000));
504 
505  p->AddByteTag (ATestTag<2> ());
506  CHECK (p, 2, E (1, 0, 1000), E (2, 0, 1000));
507  CHECK (copy, 1, E (1, 0, 1000));
508 
509  {
510  Packet c0 = *copy;
511  Packet c1 = *copy;
512  c0 = c1;
513  CHECK (&c0, 1, E (1, 0, 1000));
514  CHECK (&c1, 1, E (1, 0, 1000));
515  CHECK (copy, 1, E (1, 0, 1000));
516  c0.AddByteTag (ATestTag<10> ());
517  CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
518  CHECK (&c1, 1, E (1, 0, 1000));
519  CHECK (copy, 1, E (1, 0, 1000));
520  }
521 
522  Ptr<Packet> frag0 = p->CreateFragment (0, 10);
523  Ptr<Packet> frag1 = p->CreateFragment (10, 90);
524  Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
525  frag0->AddByteTag (ATestTag<3> ());
526  CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
527  frag1->AddByteTag (ATestTag<4> ());
528  CHECK (frag1, 3, E (1, 0, 90), E (2, 0, 90), E (4, 0, 90));
529  frag2->AddByteTag (ATestTag<5> ());
530  CHECK (frag2, 3, E (1, 0, 900), E (2, 0, 900), E (5, 0, 900));
531 
532  frag1->AddAtEnd (frag2);
533  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));
534 
535  CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
536  frag0->AddAtEnd (frag1);
537  CHECK (frag0, 9,
538  E (1, 0, 10), E (2, 0, 10), E (3, 0, 10),
539  E (1, 10, 100), E (2, 10, 100), E (4, 10, 100),
540  E (1, 100, 1000), E (2, 100, 1000), E (5, 100, 1000));
541 
542 
543  // force caching a buffer of the right size.
544  frag0 = Create<Packet> (1000);
545  frag0->AddHeader (ATestHeader<10> ());
546  frag0 = 0;
547 
548  p = Create<Packet> (1000);
549  p->AddByteTag (ATestTag<20> ());
550  CHECK (p, 1, E (20, 0, 1000));
551  frag0 = p->CreateFragment (10, 90);
552  CHECK (p, 1, E (20, 0, 1000));
553  CHECK (frag0, 1, E (20, 0, 90));
554  p = 0;
555  frag0->AddHeader (ATestHeader<10> ());
556  CHECK (frag0, 1, E (20, 10, 100));
557 
558  {
559  Ptr<Packet> tmp = Create<Packet> (100);
560  tmp->AddByteTag (ATestTag<20> ());
561  CHECK (tmp, 1, E (20, 0, 100));
562  tmp->AddHeader (ATestHeader<10> ());
563  CHECK (tmp, 1, E (20, 10, 110));
564  ATestHeader<10> h;
565  tmp->RemoveHeader (h);
566  CHECK (tmp, 1, E (20, 0, 100));
567  tmp->AddHeader (ATestHeader<10> ());
568  CHECK (tmp, 1, E (20, 10, 110));
569 
570  tmp = Create<Packet> (100);
571  tmp->AddByteTag (ATestTag<20> ());
572  CHECK (tmp, 1, E (20, 0, 100));
573  tmp->AddTrailer (ATestTrailer<10> ());
574  CHECK (tmp, 1, E (20, 0, 100));
575  ATestTrailer<10> t;
576  tmp->RemoveTrailer (t);
577  CHECK (tmp, 1, E (20, 0, 100));
578  tmp->AddTrailer (ATestTrailer<10> ());
579  CHECK (tmp, 1, E (20, 0, 100));
580 
581  }
582 
583  {
584  Ptr<Packet> tmp = Create<Packet> (0);
585  tmp->AddHeader (ATestHeader<156> ());
586  tmp->AddByteTag (ATestTag<20> ());
587  CHECK (tmp, 1, E (20, 0, 156));
588  tmp->RemoveAtStart (120);
589  CHECK (tmp, 1, E (20, 0, 36));
590  Ptr<Packet> a = Create<Packet> (0);
591  a->AddAtEnd (tmp);
592  CHECK (a, 1, E (20, 0, 36));
593  }
594 
595  {
596  Ptr<Packet> tmp = Create<Packet> (0);
597  tmp->AddByteTag (ATestTag<20> ());
598  CHECK (tmp, 0, E (20, 0, 0));
599  }
600  {
601  Ptr<Packet> tmp = Create<Packet> (1000);
602  tmp->AddByteTag (ATestTag<20> ());
603  CHECK (tmp, 1, E (20, 0, 1000));
604  tmp->RemoveAtStart (1000);
605  CHECK (tmp, 0, E (0,0,0));
606  Ptr<Packet> a = Create<Packet> (10);
607  a->AddByteTag (ATestTag<10> ());
608  CHECK (a, 1, E (10, 0, 10));
609  tmp->AddAtEnd (a);
610  CHECK (tmp, 1, E (10, 0, 10));
611  }
612 
613  {
614  Packet p;
615  ATestTag<10> a;
616  p.AddPacketTag (a);
617  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
618  ATestTag<11> b;
619  p.AddPacketTag (b);
620  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
621  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
622  Packet copy = p;
623  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
624  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
625  ATestTag<12> c;
626  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), false, "trivial");
627  copy.AddPacketTag (c);
628  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
629  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
630  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
631  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
632  copy.RemovePacketTag (b);
633  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), false, "trivial");
634  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
635  p.RemovePacketTag (a);
636  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), false, "trivial");
637  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
638  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
639  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
640  p.RemoveAllPacketTags ();
641  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), false, "trivial");
642  }
643 
644  {
647  Ptr<Packet> tmp = Create<Packet> (1000);
648  tmp->AddByteTag (ATestTag<20> ());
649  CHECK (tmp, 1, E (20, 0, 1000));
650  tmp->AddHeader (ATestHeader<2> ());
651  CHECK (tmp, 1, E (20, 2, 1002));
652  tmp->RemoveAtStart (1);
653  CHECK (tmp, 1, E (20, 1, 1001));
654 #if 0
655  tmp->PeekData ();
656  CHECK (tmp, 1, E (20, 1, 1001));
657 #endif
658  }
659 
660  /* Test reducing tagged packet size and increasing it back. */
661  {
662  Ptr<Packet> tmp = Create<Packet> (0);
663  tmp->AddHeader (ATestHeader<100> ());
664  tmp->AddByteTag (ATestTag<25> ());
665  CHECK (tmp, 1, E (25, 0, 100));
666  tmp->RemoveAtStart (50);
667  CHECK (tmp, 1, E (25, 0, 50));
668  tmp->AddHeader (ATestHeader<50> ());
669  CHECK (tmp, 1, E (25, 50, 100));
670  }
671 
672  /* Similar test case, but using trailer instead of header. */
673  {
674  Ptr<Packet> tmp = Create<Packet> (0);
675  tmp->AddTrailer (ATestTrailer<100> ());
676  tmp->AddByteTag (ATestTag<25> ());
677  CHECK (tmp, 1, E (25, 0, 100));
678  tmp->RemoveAtEnd (50);
679  CHECK (tmp, 1, E (25, 0, 50));
680  tmp->AddTrailer (ATestTrailer<50> ());
681  CHECK (tmp, 1, E (25, 0, 50));
682  }
683 
684  /* Test reducing tagged packet size and increasing it by half. */
685  {
686  Ptr<Packet> tmp = Create<Packet> (0);
687  tmp->AddHeader (ATestHeader<100> ());
688  tmp->AddByteTag (ATestTag<25> ());
689  CHECK (tmp, 1, E (25, 0, 100));
690  tmp->RemoveAtStart (50);
691  CHECK (tmp, 1, E (25, 0, 50));
692  tmp->AddHeader (ATestHeader<25> ());
693  CHECK (tmp, 1, E (25, 25, 75));
694  }
695 
696  /* Similar test case, but using trailer instead of header. */
697  {
698  Ptr<Packet> tmp = Create<Packet> (0);
699  tmp->AddTrailer (ATestTrailer<100> ());
700  tmp->AddByteTag (ATestTag<25> ());
701  CHECK (tmp, 1, E (25, 0, 100));
702  tmp->RemoveAtEnd (50);
703  CHECK (tmp, 1, E (25, 0, 50));
704  tmp->AddTrailer (ATestTrailer<25> ());
705  CHECK (tmp, 1, E (25, 0, 50));
706  }
707 
708  /* Test AddPaddingAtEnd. */
709  {
710  Ptr<Packet> tmp = Create<Packet> (0);
711  tmp->AddTrailer (ATestTrailer<100> ());
712  tmp->AddByteTag (ATestTag<25> ());
713  CHECK (tmp, 1, E (25, 0, 100));
714  tmp->RemoveAtEnd (50);
715  CHECK (tmp, 1, E (25, 0, 50));
716  tmp->AddPaddingAtEnd (50);
717  CHECK (tmp, 1, E (25, 0, 50));
718  }
719 
720  /* Test reducing tagged packet size and increasing it back,
721  * now using padding bytes to avoid triggering dirty state
722  * in virtual buffer
723  */
724  {
725  Ptr<Packet> tmp = Create<Packet> (100);
726  tmp->AddByteTag (ATestTag<25> ());
727  CHECK (tmp, 1, E (25, 0, 100));
728  tmp->RemoveAtEnd (50);
729  CHECK (tmp, 1, E (25, 0, 50));
730  tmp->AddPaddingAtEnd (50);
731  CHECK (tmp, 1, E (25, 0, 50));
732  }
733 
734  /* Test ALargeTestTag */
735  {
736  Ptr<Packet> tmp = Create<Packet> (0);
737  ALargeTestTag a;
738  tmp->AddPacketTag (a);
739  }
740 }
741 
749 {
750 public:
752  virtual ~PacketTagListTest ();
753 private:
754  void DoRun (void);
762  void CheckRef (const PacketTagList & ref,
763  ATestTagBase & t,
764  const char * msg,
765  bool miss = false);
772  void CheckRefList (const PacketTagList & ref,
773  const char * msg,
774  int miss = 0);
775 
783  int RemoveTime (const PacketTagList & ref,
784  ATestTagBase & t,
785  const char * msg = 0);
786 
792  int AddRemoveTime (const bool verbose = false);
793 };
794 
796  : TestCase ("PacketTagListTest: ")
797 {
798 }
799 
801 {
802 }
803 
804 void
806  ATestTagBase & t,
807  const char * msg,
808  bool miss)
809 {
810  int expect = t.GetData (); // the value we should find
811  bool found = ref.Peek (t); // rewrites t with actual value
812  NS_TEST_EXPECT_MSG_EQ (found, !miss,
813  msg << ": ref contains "
814  << t.GetTypeId ().GetName ());
815  if (found) {
816  NS_TEST_EXPECT_MSG_EQ (t.GetData (), expect,
817  msg << ": ref " << t.GetTypeId ().GetName ()
818  << " = " << expect);
819  }
820 }
821 
822  // A set of tags with data value 1, to check COW
823 #define MAKE_TEST_TAGS \
824  ATestTag<1> t1 (1); \
825  ATestTag<2> t2 (1); \
826  ATestTag<3> t3 (1); \
827  ATestTag<4> t4 (1); \
828  ATestTag<5> t5 (1); \
829  ATestTag<6> t6 (1); \
830  ATestTag<7> t7 (1); \
831  const int tagLast = 7; /* length of ref PacketTagList */ \
832  NS_UNUSED (tagLast) /* silence warnings */
833 
834 
835 
836 void
838  const char * msg,
839  int miss /* = 0 */)
840 {
842  CheckRef (ptl, t1, msg, miss == 1);
843  CheckRef (ptl, t2, msg, miss == 2);
844  CheckRef (ptl, t3, msg, miss == 3);
845  CheckRef (ptl, t4, msg, miss == 4);
846  CheckRef (ptl, t5, msg, miss == 5);
847  CheckRef (ptl, t6, msg, miss == 6);
848  CheckRef (ptl, t7, msg, miss == 7);
849 }
850 
851 int
853  ATestTagBase & t,
854  const char * msg /* = 0 */)
855 {
856  const int reps = 10000;
857  std::vector< PacketTagList > ptv(reps, ref);
858  int start = clock ();
859  for (int i = 0; i < reps; ++i) {
860  ptv[i].Remove (t);
861  }
862  int stop = clock ();
863  int delta = stop - start;
864  if (msg) {
865  std::cout << GetName () << "remove time: " << msg << ": " << std::setw (8)
866  << delta << " ticks to remove "
867  << reps << " times"
868  << std::endl;
869  }
870  return delta;
871 }
872 
873 int
874 PacketTagListTest::AddRemoveTime (const bool verbose /* = false */)
875 {
876  const int reps = 100000;
877  PacketTagList ptl;
878  ATestTag <2> t(2);
879  int start = clock ();
880  for (int i = 0; i < reps; ++i) {
881  ptl.Add (t);
882  ptl.Remove (t);
883  }
884  int stop = clock ();
885  int delta = stop - start;
886  if (verbose) {
887  std::cout << GetName () << "add/remove time: " << std::setw (8)
888  << delta << " ticks to add+remove "
889  << reps << " times"
890  << std::endl;
891  }
892  return delta;
893 }
894 
895 void
897 {
898  std::cout << GetName () << "begin" << std::endl;
899 
901 
902  PacketTagList ref; // empty list
903  ref.Add (t1); // last
904  ref.Add (t2); // post merge
905  ref.Add (t3); // merge successor
906  ref.Add (t4); // merge
907  ref.Add (t5); // merge precursor
908  ref.Add (t6); // pre-merge
909  ref.Add (t7); // first
910 
911  { // Peek
912  std::cout << GetName () << "check Peek (missing tag) returns false"
913  << std::endl;
914  ATestTag<10> t10;
915  NS_TEST_EXPECT_MSG_EQ (ref.Peek (t10), false, "missing tag");
916  }
917 
918  { // Copy ctor, assignment
919  std::cout << GetName () << "check copy and assignment" << std::endl;
920  { PacketTagList ptl (ref);
921  CheckRefList (ref, "copy ctor orig");
922  CheckRefList (ptl, "copy ctor copy");
923  }
924  { PacketTagList ptl = ref;
925  CheckRefList (ref, "assignment orig");
926  CheckRefList (ptl, "assignment copy");
927  }
928  }
929 
930  { // Removal
931 # define RemoveCheck(n) \
932  { PacketTagList p ## n = ref; \
933  p ## n .Remove ( t ## n ); \
934  CheckRefList (ref, "remove " #n " orig"); \
935  CheckRefList (p ## n, "remove " #n " copy", n); \
936  }
937 
938  { // Remove single tags from list
939  std::cout << GetName () << "check removal of each tag" << std::endl;
940  RemoveCheck (1);
941  RemoveCheck (2);
942  RemoveCheck (3);
943  RemoveCheck (4);
944  RemoveCheck (5);
945  RemoveCheck (6);
946  RemoveCheck (7);
947  }
948 
949  { // Remove in the presence of a merge
950  std::cout << GetName () << "check removal doesn't disturb merge "
951  << std::endl;
952  PacketTagList ptl = ref;
953  ptl.Remove (t7);
954  ptl.Remove (t6);
955  ptl.Remove (t5);
956 
957  PacketTagList mrg = ptl; // merged list
958  ATestTag<8> m5 (1);
959  mrg.Add (m5); // ptl and mrg differ
960  ptl.Add (t5);
961  ptl.Add (t6);
962  ptl.Add (t7);
963 
964  CheckRefList (ref, "post merge, orig");
965  CheckRefList (ptl, "post merge, long chain");
966  const char * msg = "post merge, short chain";
967  CheckRef (mrg, t1, msg, false);
968  CheckRef (mrg, t2, msg, false);
969  CheckRef (mrg, t3, msg, false);
970  CheckRef (mrg, t4, msg, false);
971  CheckRef (mrg, m5, msg, false);
972  }
973 # undef RemoveCheck
974  } // Removal
975 
976  { // Replace
977 
978  std::cout << GetName () << "check replacing each tag" << std::endl;
979 
980 # define ReplaceCheck(n) \
981  t ## n .m_data = 2; \
982  { PacketTagList p ## n = ref; \
983  p ## n .Replace ( t ## n ); \
984  CheckRefList (ref, "replace " #n " orig"); \
985  CheckRef (p ## n, t ## n, "replace " #n " copy"); \
986  }
987 
988  ReplaceCheck (1);
989  ReplaceCheck (2);
990  ReplaceCheck (3);
991  ReplaceCheck (4);
992  ReplaceCheck (5);
993  ReplaceCheck (6);
994  ReplaceCheck (7);
995  }
996 
997  { // Timing
998  std::cout << GetName () << "add+remove timing" << std::endl;
999  int flm = std::numeric_limits<int>::max ();
1000  const int nIterations = 100;
1001  for (int i = 0; i < nIterations; ++i) {
1002  int now = AddRemoveTime ();
1003  if (now < flm) flm = now;
1004  }
1005  std::cout << GetName () << "min add+remove time: "
1006  << std::setw (8) << flm << " ticks"
1007  << std::endl;
1008 
1009  std::cout << GetName () << "remove timing" << std::endl;
1010  // tags numbered from 1, so add one for (unused) entry at 0
1011  std::vector <int> rmn (tagLast + 1, std::numeric_limits<int>::max ());
1012  for (int i = 0; i < nIterations; ++i) {
1013  for (int j = 1; j <= tagLast; ++j) {
1014  int now = 0;
1015  switch (j) {
1016  case 7: now = RemoveTime (ref, t7); break;
1017  case 6: now = RemoveTime (ref, t6); break;
1018  case 5: now = RemoveTime (ref, t5); break;
1019  case 4: now = RemoveTime (ref, t4); break;
1020  case 3: now = RemoveTime (ref, t3); break;
1021  case 2: now = RemoveTime (ref, t2); break;
1022  case 1: now = RemoveTime (ref, t1); break;
1023  } // switch
1024 
1025  if (now < rmn[j]) rmn[j] = now;
1026  } // for tag j
1027  } // for iteration i
1028  for (int j = tagLast; j > 0; --j) {
1029  std::cout << GetName () << "min remove time: t"
1030  << j << ": "
1031  << std::setw (8) << rmn[j] << " ticks"
1032  << std::endl;
1033  }
1034  } // Timing
1035 
1036 }
1037 
1045 {
1046 public:
1047  PacketTestSuite ();
1048 };
1049 
1051  : TestSuite ("packet", UNIT)
1052 {
1053  AddTestCase (new PacketTest, TestCase::QUICK);
1054  AddTestCase (new PacketTagListTest, TestCase::QUICK);
1055 }
1056 
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:1053
TypeId GetTypeId(void) const
Definition: packet.cc:34
std::string GetName(void) const
Get the name.
Definition: type-id.cc:969
Packet Tag list unit tests.
TypeId AddConstructor(void)
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:652
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)
A suite of tests to run.
Definition: test.h:1342
def start()
Definition: core.py:1858
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:285
Packet unit tests.
encapsulates test code
Definition: test.h:1155
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:891
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
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
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:922
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:739
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:238
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
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:863
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:870
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:885
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.
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:819
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:840
bool verbose
TypeId HideFromDocumentation(void)
Hide this TypeId from documentation.
Definition: type-id.cc:1128
#define E(a, b, c)
#define CHECK(p, n,...)
int AddRemoveTime(const bool verbose=false)
Prints the remove time.