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 
38 class ATestTagBase : public Tag
39 {
40 public:
41  ATestTagBase () : m_error (false), m_data (0) {}
42  ATestTagBase (uint8_t data) : m_error (false), m_data (data) {}
47  static TypeId GetTypeId (void)
48  {
49  static TypeId tid = TypeId ("ATestTagBase")
50  .SetParent<Tag> ()
51  .SetGroupName ("Network")
52  .HideFromDocumentation ()
53  // No AddConstructor because this is an abstract class.
54  ;
55  return tid;
56  }
57  int GetData () const {
58  int result = (int)m_data;
59  return result;
60  }
61  bool m_error;
62  uint8_t m_data;
63 };
64 
65 template <int N>
66 class ATestTag : public ATestTagBase
67 {
68 public:
73  static TypeId GetTypeId (void) {
74  std::ostringstream oss;
75  oss << "anon::ATestTag<" << N << ">";
76  static TypeId tid = TypeId (oss.str ().c_str ())
77  .SetParent<ATestTagBase> ()
78  .SetGroupName ("Network")
81  ;
82  return tid;
83  }
84  virtual TypeId GetInstanceTypeId (void) const {
85  return GetTypeId ();
86  }
87  virtual uint32_t GetSerializedSize (void) const {
88  return N + sizeof(m_data);
89  }
90  virtual void Serialize (TagBuffer buf) const {
91  buf.WriteU8 (m_data);
92  for (uint32_t i = 0; i < N; ++i)
93  {
94  buf.WriteU8 (N);
95  }
96  }
97  virtual void Deserialize (TagBuffer buf) {
98  m_data = buf.ReadU8 ();
99  for (uint32_t i = 0; i < N; ++i)
100  {
101  uint8_t v = buf.ReadU8 ();
102  if (v != N)
103  {
104  m_error = true;
105  }
106  }
107  }
108  virtual void Print (std::ostream &os) const {
109  os << N << "(" << m_data << ")";
110  }
112  : ATestTagBase () {}
113  ATestTag (uint8_t data)
114  : ATestTagBase (data) {}
115 };
116 
117 class ATestHeaderBase : public Header
118 {
119 public:
120  ATestHeaderBase () : Header (), m_error (false) {}
125  static TypeId GetTypeId (void)
126  {
127  static TypeId tid = TypeId ("ATestHeaderBase")
128  .SetParent<Header> ()
129  .SetGroupName ("Network")
130  .HideFromDocumentation ()
131  // No AddConstructor because this is an abstract class.
132  ;
133  return tid;
134  }
135  bool m_error;
136 };
137 
138 template <int N>
140 {
141 public:
146  static TypeId GetTypeId (void) {
147  std::ostringstream oss;
148  oss << "anon::ATestHeader<" << N << ">";
149  static TypeId tid = TypeId (oss.str ().c_str ())
150  .SetParent<ATestHeaderBase> ()
151  .SetGroupName ("Network")
154  ;
155  return tid;
156  }
157  virtual TypeId GetInstanceTypeId (void) const {
158  return GetTypeId ();
159  }
160  virtual uint32_t GetSerializedSize (void) const {
161  return N;
162  }
163  virtual void Serialize (Buffer::Iterator iter) const {
164  for (uint32_t i = 0; i < N; ++i)
165  {
166  iter.WriteU8 (N);
167  }
168  }
169  virtual uint32_t Deserialize (Buffer::Iterator iter) {
170  for (uint32_t i = 0; i < N; ++i)
171  {
172  uint8_t v = iter.ReadU8 ();
173  if (v != N)
174  {
175  m_error = true;
176  }
177  }
178  return N;
179  }
180  virtual void Print (std::ostream &os) const {
181  }
183  : ATestHeaderBase () {}
184 
185 };
186 
187 class ATestTrailerBase : public Trailer
188 {
189 public:
190  ATestTrailerBase () : Trailer (), m_error (false) {}
195  static TypeId GetTypeId (void)
196  {
197  static TypeId tid = TypeId ("ATestTrailerBase")
198  .SetParent<Trailer> ()
199  .SetGroupName ("Network")
200  .HideFromDocumentation ()
201  // No AddConstructor because this is an abstract class.
202  ;
203  return tid;
204  }
205  bool m_error;
206 };
207 
208 template <int N>
210 {
211 public:
216  static TypeId GetTypeId (void) {
217  std::ostringstream oss;
218  oss << "anon::ATestTrailer<" << N << ">";
219  static TypeId tid = TypeId (oss.str ().c_str ())
220  .SetParent<ATestTrailerBase> ()
221  .SetGroupName ("Network")
224  ;
225  return tid;
226  }
227  virtual TypeId GetInstanceTypeId (void) const {
228  return GetTypeId ();
229  }
230  virtual uint32_t GetSerializedSize (void) const {
231  return N;
232  }
233  virtual void Serialize (Buffer::Iterator iter) const {
234  iter.Prev (N);
235  for (uint32_t i = 0; i < N; ++i)
236  {
237  iter.WriteU8 (N);
238  }
239  }
240  virtual uint32_t Deserialize (Buffer::Iterator iter) {
241  iter.Prev (N);
242  for (uint32_t i = 0; i < N; ++i)
243  {
244  uint8_t v = iter.ReadU8 ();
245  if (v != N)
246  {
247  m_error = true;
248  }
249  }
250  return N;
251  }
252  virtual void Print (std::ostream &os) const {
253  }
255  : ATestTrailerBase () {}
256 
257 };
258 
259 
260 struct Expected
261 {
262  Expected (uint32_t n_, uint32_t start_, uint32_t end_)
263  : n (n_), start (start_), end (end_) {}
264 
265  uint32_t n;
266  uint32_t start;
267  uint32_t end;
268 };
269 
270 }
271 
272 // tag name, start, end
273 #define E(a,b,c) a,b,c
274 
275 #define CHECK(p, n, ...) \
276  DoCheck (p, __FILE__, __LINE__, n, __VA_ARGS__)
277 
278 class PacketTest : public TestCase
279 {
280 public:
281  PacketTest ();
282  virtual void DoRun (void);
283 private:
284  void DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
285 };
286 
287 
289  : TestCase ("Packet") {
290 }
291 
292 void
293 PacketTest::DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
294 {
295  std::vector<struct Expected> expected;
296  va_list ap;
297  va_start (ap, n);
298  for (uint32_t k = 0; k < n; ++k)
299  {
300  uint32_t N = va_arg (ap, uint32_t);
301  uint32_t start = va_arg (ap, uint32_t);
302  uint32_t end = va_arg (ap, uint32_t);
303  expected.push_back (Expected (N, start, end));
304  }
305  va_end (ap);
306 
308  uint32_t j = 0;
309  while (i.HasNext () && j < expected.size ())
310  {
311  ByteTagIterator::Item item = i.Next ();
312  struct Expected e = expected[j];
313  std::ostringstream oss;
314  oss << "anon::ATestTag<" << e.n << ">";
315  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetTypeId ().GetName (), oss.str (), "trivial", file, line);
316  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetStart (), e.start, "trivial", file, line);
317  NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetEnd (), e.end, "trivial", file, line);
318  ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
319  NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
320  item.GetTag (*tag);
321  NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
322  delete tag;
323  j++;
324  }
325  NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
326  NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
327 }
328 
329 void
331 {
332  Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
333  Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
334  Ptr<Packet> packet = Create<Packet> ();
335  packet->AddAtEnd (pkt1);
336  packet->AddAtEnd (pkt2);
337 
338  NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 11, "trivial");
339 
340  uint8_t *buf = new uint8_t[packet->GetSize ()];
341  packet->CopyData (buf, packet->GetSize ());
342 
343  std::string msg = std::string (reinterpret_cast<const char *>(buf),
344  packet->GetSize ());
345  delete [] buf;
346 
347  NS_TEST_EXPECT_MSG_EQ (msg, "hello world", "trivial");
348 
349 
350  Ptr<const Packet> p = Create<Packet> (1000);
351 
352  p->AddByteTag (ATestTag<1> ());
353  CHECK (p, 1, E (1, 0, 1000));
354  Ptr<const Packet> copy = p->Copy ();
355  CHECK (copy, 1, E (1, 0, 1000));
356 
357  p->AddByteTag (ATestTag<2> ());
358  CHECK (p, 2, E (1, 0, 1000), E (2, 0, 1000));
359  CHECK (copy, 1, E (1, 0, 1000));
360 
361  {
362  Packet c0 = *copy;
363  Packet c1 = *copy;
364  c0 = c1;
365  CHECK (&c0, 1, E (1, 0, 1000));
366  CHECK (&c1, 1, E (1, 0, 1000));
367  CHECK (copy, 1, E (1, 0, 1000));
368  c0.AddByteTag (ATestTag<10> ());
369  CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
370  CHECK (&c1, 1, E (1, 0, 1000));
371  CHECK (copy, 1, E (1, 0, 1000));
372  }
373 
374  Ptr<Packet> frag0 = p->CreateFragment (0, 10);
375  Ptr<Packet> frag1 = p->CreateFragment (10, 90);
376  Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
377  frag0->AddByteTag (ATestTag<3> ());
378  CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
379  frag1->AddByteTag (ATestTag<4> ());
380  CHECK (frag1, 3, E (1, 0, 90), E (2, 0, 90), E (4, 0, 90));
381  frag2->AddByteTag (ATestTag<5> ());
382  CHECK (frag2, 3, E (1, 0, 900), E (2, 0, 900), E (5, 0, 900));
383 
384  frag1->AddAtEnd (frag2);
385  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));
386 
387  CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
388  frag0->AddAtEnd (frag1);
389  CHECK (frag0, 9,
390  E (1, 0, 10), E (2, 0, 10), E (3, 0, 10),
391  E (1, 10, 100), E (2, 10, 100), E (4, 10, 100),
392  E (1, 100, 1000), E (2, 100, 1000), E (5, 100, 1000));
393 
394 
395  // force caching a buffer of the right size.
396  frag0 = Create<Packet> (1000);
397  frag0->AddHeader (ATestHeader<10> ());
398  frag0 = 0;
399 
400  p = Create<Packet> (1000);
401  p->AddByteTag (ATestTag<20> ());
402  CHECK (p, 1, E (20, 0, 1000));
403  frag0 = p->CreateFragment (10, 90);
404  CHECK (p, 1, E (20, 0, 1000));
405  CHECK (frag0, 1, E (20, 0, 90));
406  p = 0;
407  frag0->AddHeader (ATestHeader<10> ());
408  CHECK (frag0, 1, E (20, 10, 100));
409 
410  {
411  Ptr<Packet> tmp = Create<Packet> (100);
412  tmp->AddByteTag (ATestTag<20> ());
413  CHECK (tmp, 1, E (20, 0, 100));
414  tmp->AddHeader (ATestHeader<10> ());
415  CHECK (tmp, 1, E (20, 10, 110));
416  ATestHeader<10> h;
417  tmp->RemoveHeader (h);
418  CHECK (tmp, 1, E (20, 0, 100));
419  tmp->AddHeader (ATestHeader<10> ());
420  CHECK (tmp, 1, E (20, 10, 110));
421 
422  tmp = Create<Packet> (100);
423  tmp->AddByteTag (ATestTag<20> ());
424  CHECK (tmp, 1, E (20, 0, 100));
425  tmp->AddTrailer (ATestTrailer<10> ());
426  CHECK (tmp, 1, E (20, 0, 100));
427  ATestTrailer<10> t;
428  tmp->RemoveTrailer (t);
429  CHECK (tmp, 1, E (20, 0, 100));
430  tmp->AddTrailer (ATestTrailer<10> ());
431  CHECK (tmp, 1, E (20, 0, 100));
432 
433  }
434 
435  {
436  Ptr<Packet> tmp = Create<Packet> (0);
437  tmp->AddHeader (ATestHeader<156> ());
438  tmp->AddByteTag (ATestTag<20> ());
439  CHECK (tmp, 1, E (20, 0, 156));
440  tmp->RemoveAtStart (120);
441  CHECK (tmp, 1, E (20, 0, 36));
442  Ptr<Packet> a = Create<Packet> (0);
443  a->AddAtEnd (tmp);
444  CHECK (a, 1, E (20, 0, 36));
445  }
446 
447  {
448  Ptr<Packet> tmp = Create<Packet> (0);
449  tmp->AddByteTag (ATestTag<20> ());
450  CHECK (tmp, 0, E (20, 0, 0));
451  }
452  {
453  Ptr<Packet> tmp = Create<Packet> (1000);
454  tmp->AddByteTag (ATestTag<20> ());
455  CHECK (tmp, 1, E (20, 0, 1000));
456  tmp->RemoveAtStart (1000);
457  CHECK (tmp, 0, E (0,0,0));
458  Ptr<Packet> a = Create<Packet> (10);
459  a->AddByteTag (ATestTag<10> ());
460  CHECK (a, 1, E (10, 0, 10));
461  tmp->AddAtEnd (a);
462  CHECK (tmp, 1, E (10, 0, 10));
463  }
464 
465  {
466  Packet p;
467  ATestTag<10> a;
468  p.AddPacketTag (a);
469  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
470  ATestTag<11> b;
471  p.AddPacketTag (b);
472  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
473  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
474  Packet copy = p;
475  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
476  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
477  ATestTag<12> c;
478  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), false, "trivial");
479  copy.AddPacketTag (c);
480  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
481  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
482  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
483  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
484  copy.RemovePacketTag (b);
485  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), false, "trivial");
486  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
487  p.RemovePacketTag (a);
488  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), false, "trivial");
489  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
490  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
491  NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
492  p.RemoveAllPacketTags ();
493  NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), false, "trivial");
494  }
495 
496  {
499  Ptr<Packet> tmp = Create<Packet> (1000);
500  tmp->AddByteTag (ATestTag<20> ());
501  CHECK (tmp, 1, E (20, 0, 1000));
502  tmp->AddHeader (ATestHeader<2> ());
503  CHECK (tmp, 1, E (20, 2, 1002));
504  tmp->RemoveAtStart (1);
505  CHECK (tmp, 1, E (20, 1, 1001));
506 #if 0
507  tmp->PeekData ();
508  CHECK (tmp, 1, E (20, 1, 1001));
509 #endif
510  }
511 
512  /* Test reducing tagged packet size and increasing it back. */
513  {
514  Ptr<Packet> tmp = Create<Packet> (0);
515  tmp->AddHeader (ATestHeader<100> ());
516  tmp->AddByteTag (ATestTag<25> ());
517  CHECK (tmp, 1, E (25, 0, 100));
518  tmp->RemoveAtStart (50);
519  CHECK (tmp, 1, E (25, 0, 50));
520  tmp->AddHeader (ATestHeader<50> ());
521  CHECK (tmp, 1, E (25, 50, 100));
522  }
523 
524  /* Similar test case, but using trailer instead of header. */
525  {
526  Ptr<Packet> tmp = Create<Packet> (0);
527  tmp->AddTrailer (ATestTrailer<100> ());
528  tmp->AddByteTag (ATestTag<25> ());
529  CHECK (tmp, 1, E (25, 0, 100));
530  tmp->RemoveAtEnd (50);
531  CHECK (tmp, 1, E (25, 0, 50));
532  tmp->AddTrailer (ATestTrailer<50> ());
533  CHECK (tmp, 1, E (25, 0, 50));
534  }
535 
536  /* Test reducing tagged packet size and increasing it by half. */
537  {
538  Ptr<Packet> tmp = Create<Packet> (0);
539  tmp->AddHeader (ATestHeader<100> ());
540  tmp->AddByteTag (ATestTag<25> ());
541  CHECK (tmp, 1, E (25, 0, 100));
542  tmp->RemoveAtStart (50);
543  CHECK (tmp, 1, E (25, 0, 50));
544  tmp->AddHeader (ATestHeader<25> ());
545  CHECK (tmp, 1, E (25, 25, 75));
546  }
547 
548  /* Similar test case, but using trailer instead of header. */
549  {
550  Ptr<Packet> tmp = Create<Packet> (0);
551  tmp->AddTrailer (ATestTrailer<100> ());
552  tmp->AddByteTag (ATestTag<25> ());
553  CHECK (tmp, 1, E (25, 0, 100));
554  tmp->RemoveAtEnd (50);
555  CHECK (tmp, 1, E (25, 0, 50));
556  tmp->AddTrailer (ATestTrailer<25> ());
557  CHECK (tmp, 1, E (25, 0, 50));
558  }
559 
560  /* Test AddPaddingAtEnd. */
561  {
562  Ptr<Packet> tmp = Create<Packet> (0);
563  tmp->AddTrailer (ATestTrailer<100> ());
564  tmp->AddByteTag (ATestTag<25> ());
565  CHECK (tmp, 1, E (25, 0, 100));
566  tmp->RemoveAtEnd (50);
567  CHECK (tmp, 1, E (25, 0, 50));
568  tmp->AddPaddingAtEnd (50);
569  CHECK (tmp, 1, E (25, 0, 50));
570  }
571 
572  /* Test reducing tagged packet size and increasing it back,
573  * now using padding bytes to avoid triggering dirty state
574  * in virtual buffer
575  */
576  {
577  Ptr<Packet> tmp = Create<Packet> (100);
578  tmp->AddByteTag (ATestTag<25> ());
579  CHECK (tmp, 1, E (25, 0, 100));
580  tmp->RemoveAtEnd (50);
581  CHECK (tmp, 1, E (25, 0, 50));
582  tmp->AddPaddingAtEnd (50);
583  CHECK (tmp, 1, E (25, 0, 50));
584  }
585 }
586 //--------------------------------------
588 {
589 public:
591  virtual ~PacketTagListTest ();
592 private:
593  void DoRun (void);
594  void CheckRef (const PacketTagList & ref,
595  ATestTagBase & t,
596  const char * msg,
597  bool miss = false);
598  void CheckRefList (const PacketTagList & ref,
599  const char * msg,
600  int miss = 0);
601  int RemoveTime (const PacketTagList & ref,
602  ATestTagBase & t,
603  const char * msg = 0);
604  int AddRemoveTime (const bool verbose = false);
605 };
606 
608  : TestCase ("PacketTagListTest: ")
609 {
610 }
611 
613 {
614 }
615 
616 void
618  ATestTagBase & t,
619  const char * msg,
620  bool miss)
621 {
622  int expect = t.GetData (); // the value we should find
623  bool found = ref.Peek (t); // rewrites t with actual value
624  NS_TEST_EXPECT_MSG_EQ (found, !miss,
625  msg << ": ref contains "
626  << t.GetTypeId ().GetName ());
627  if (found) {
628  NS_TEST_EXPECT_MSG_EQ (t.GetData (), expect,
629  msg << ": ref " << t.GetTypeId ().GetName ()
630  << " = " << expect);
631  }
632 }
633 
634  // A set of tags with data value 1, to check COW
635 #define MAKE_TEST_TAGS \
636  ATestTag<1> t1 (1); \
637  ATestTag<2> t2 (1); \
638  ATestTag<3> t3 (1); \
639  ATestTag<4> t4 (1); \
640  ATestTag<5> t5 (1); \
641  ATestTag<6> t6 (1); \
642  ATestTag<7> t7 (1); \
643  const int tagLast = 7; /* length of ref PacketTagList */ \
644  NS_UNUSED (tagLast) /* silence warnings */
645 
646 
647 
648 void
650  const char * msg,
651  int miss /* = 0 */)
652 {
654  CheckRef (ptl, t1, msg, miss == 1);
655  CheckRef (ptl, t2, msg, miss == 2);
656  CheckRef (ptl, t3, msg, miss == 3);
657  CheckRef (ptl, t4, msg, miss == 4);
658  CheckRef (ptl, t5, msg, miss == 5);
659  CheckRef (ptl, t6, msg, miss == 6);
660  CheckRef (ptl, t7, msg, miss == 7);
661 }
662 
663 int
665  ATestTagBase & t,
666  const char * msg /* = 0 */)
667 {
668  const int reps = 10000;
669  std::vector< PacketTagList > ptv(reps, ref);
670  int start = clock ();
671  for (int i = 0; i < reps; ++i) {
672  ptv[i].Remove (t);
673  }
674  int stop = clock ();
675  int delta = stop - start;
676  if (msg) {
677  std::cout << GetName () << "remove time: " << msg << ": " << std::setw (8)
678  << delta << " ticks to remove "
679  << reps << " times"
680  << std::endl;
681  }
682  return delta;
683 }
684 
685 int
686 PacketTagListTest::AddRemoveTime (const bool verbose /* = false */)
687 {
688  const int reps = 100000;
689  PacketTagList ptl;
690  ATestTag <2> t(2);
691  int start = clock ();
692  for (int i = 0; i < reps; ++i) {
693  ptl.Add (t);
694  ptl.Remove (t);
695  }
696  int stop = clock ();
697  int delta = stop - start;
698  if (verbose) {
699  std::cout << GetName () << "add/remove time: " << std::setw (8)
700  << delta << " ticks to add+remove "
701  << reps << " times"
702  << std::endl;
703  }
704  return delta;
705 }
706 
707 void
709 {
710  std::cout << GetName () << "begin" << std::endl;
711 
713 
714  PacketTagList ref; // empty list
715  ref.Add (t1); // last
716  ref.Add (t2); // post merge
717  ref.Add (t3); // merge successor
718  ref.Add (t4); // merge
719  ref.Add (t5); // merge precursor
720  ref.Add (t6); // pre-merge
721  ref.Add (t7); // first
722 
723  { // Peek
724  std::cout << GetName () << "check Peek (missing tag) returns false"
725  << std::endl;;
726  ATestTag<10> t10;
727  NS_TEST_EXPECT_MSG_EQ (ref.Peek (t10), false, "missing tag");
728  }
729 
730  { // Copy ctor, assignment
731  std::cout << GetName () << "check copy and assignment" << std::endl;
732  { PacketTagList ptl (ref);
733  CheckRefList (ref, "copy ctor orig");
734  CheckRefList (ptl, "copy ctor copy");
735  }
736  { PacketTagList ptl = ref;
737  CheckRefList (ref, "assignment orig");
738  CheckRefList (ptl, "assignment copy");
739  }
740  }
741 
742  { // Removal
743 # define RemoveCheck(n) \
744  { PacketTagList p ## n = ref; \
745  p ## n .Remove ( t ## n ); \
746  CheckRefList (ref, "remove " #n " orig"); \
747  CheckRefList (p ## n, "remove " #n " copy", n); \
748  }
749 
750  { // Remove single tags from list
751  std::cout << GetName () << "check removal of each tag" << std::endl;
752  RemoveCheck (1);
753  RemoveCheck (2);
754  RemoveCheck (3);
755  RemoveCheck (4);
756  RemoveCheck (5);
757  RemoveCheck (6);
758  RemoveCheck (7);
759  }
760 
761  { // Remove in the presence of a merge
762  std::cout << GetName () << "check removal doesn't disturb merge "
763  << std::endl;
764  PacketTagList ptl = ref;
765  ptl.Remove (t7);
766  ptl.Remove (t6);
767  ptl.Remove (t5);
768 
769  PacketTagList mrg = ptl; // merged list
770  ATestTag<8> m5 (1);
771  mrg.Add (m5); // ptl and mrg differ
772  ptl.Add (t5);
773  ptl.Add (t6);
774  ptl.Add (t7);
775 
776  CheckRefList (ref, "post merge, orig");
777  CheckRefList (ptl, "post merge, long chain");
778  const char * msg = "post merge, short chain";
779  CheckRef (mrg, t1, msg, false);
780  CheckRef (mrg, t2, msg, false);
781  CheckRef (mrg, t3, msg, false);
782  CheckRef (mrg, t4, msg, false);
783  CheckRef (mrg, m5, msg, false);
784  }
785 # undef RemoveCheck
786  } // Removal
787 
788  { // Replace
789 
790  std::cout << GetName () << "check replacing each tag" << std::endl;
791 
792 # define ReplaceCheck(n) \
793  t ## n .m_data = 2; \
794  { PacketTagList p ## n = ref; \
795  p ## n .Replace ( t ## n ); \
796  CheckRefList (ref, "replace " #n " orig"); \
797  CheckRef (p ## n, t ## n, "replace " #n " copy"); \
798  }
799 
800  ReplaceCheck (1);
801  ReplaceCheck (2);
802  ReplaceCheck (3);
803  ReplaceCheck (4);
804  ReplaceCheck (5);
805  ReplaceCheck (6);
806  ReplaceCheck (7);
807  }
808 
809  { // Timing
810  std::cout << GetName () << "add+remove timing" << std::endl;
811  int flm = std::numeric_limits<int>::max ();
812  const int nIterations = 100;
813  for (int i = 0; i < nIterations; ++i) {
814  int now = AddRemoveTime ();
815  if (now < flm) flm = now;
816  }
817  std::cout << GetName () << "min add+remove time: "
818  << std::setw (8) << flm << " ticks"
819  << std::endl;
820 
821  std::cout << GetName () << "remove timing" << std::endl;
822  // tags numbered from 1, so add one for (unused) entry at 0
823  std::vector <int> rmn (tagLast + 1, std::numeric_limits<int>::max ());
824  for (int i = 0; i < nIterations; ++i) {
825  for (int j = 1; j <= tagLast; ++j) {
826  int now = 0;
827  switch (j) {
828  case 7: now = RemoveTime (ref, t7); break;
829  case 6: now = RemoveTime (ref, t6); break;
830  case 5: now = RemoveTime (ref, t5); break;
831  case 4: now = RemoveTime (ref, t4); break;
832  case 3: now = RemoveTime (ref, t3); break;
833  case 2: now = RemoveTime (ref, t2); break;
834  case 1: now = RemoveTime (ref, t1); break;
835  } // switch
836 
837  if (now < rmn[j]) rmn[j] = now;
838  } // for tag j
839  } // for iteration i
840  for (int j = tagLast; j > 0; --j) {
841  std::cout << GetName () << "min remove time: t"
842  << j << ": "
843  << std::setw (8) << rmn[j] << " ticks"
844  << std::endl;
845  }
846  } // Timing
847 
848 }
849 
850 //-----------------------------------------------------------------------------
852 {
853 public:
854  PacketTestSuite ();
855 };
856 
858  : TestSuite ("packet", UNIT)
859 {
860  AddTestCase (new PacketTest, TestCase::QUICK);
861  AddTestCase (new PacketTagListTest, TestCase::QUICK);
862 }
863 
bool HasNext(void) const
Definition: packet.cc:65
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:268
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.
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)
virtual void Serialize(Buffer::Iterator iter) const
virtual uint32_t Deserialize(Buffer::Iterator iter)
A suite of tests to run.
Definition: test.h:1333
def start()
Definition: core.py:1482
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:824
List of the packet tags stored in a packet.
#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:278
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
encapsulates test code
Definition: test.h:1147
static TypeId GetTypeId(void)
Register this type.
Expected(uint32_t n_, uint32_t start_, uint32_t end_)
network packets
Definition: packet.h:227
virtual void Print(std::ostream &os) const
bool Peek(Tag &tag) const
Find a tag and return its value.
TAG_BUFFER_INLINE uint8_t ReadU8(void)
Definition: tag-buffer.h:195
iterator in a Buffer instance
Definition: buffer.h:98
Callback< ObjectBase * > GetConstructor(void) const
Get the constructor callback.
Definition: type-id.cc:1042
void Add(Tag const &tag) const
Add a tag to the head of this branch.
#define MAKE_TEST_TAGS
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:228
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:313
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:846
void RemoveAllPacketTags(void)
Remove all packet tags.
Definition: packet.cc:852
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:340
#define max(a, b)
Definition: 80211b.c:45
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:298
void Prev(void)
go backward by one byte
Definition: buffer.h:850
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:325
ByteTagIterator GetByteTagIterator(void) const
Returns an iterator over the set of byte tags included in this packet.
Definition: packet.cc:801
static TypeId GetTypeId(void)
Register this type.
Item Next(void)
Definition: packet.cc:70
uint32_t GetEnd(void) const
The index is an offset from the start of the packet.
Definition: packet.cc:44
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
TypeId SetGroupName(std::string groupName)
Set the group name.
Definition: type-id.cc:911
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
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)
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Definition: packet.cc:285
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:333
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:296
#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:732
std::string GetName(void) const
Get the name.
Definition: type-id.cc:958
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:172
TypeId GetTypeId(void) const
Definition: packet.cc:34
#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:231
void CheckRef(const PacketTagList &ref, ATestTagBase &t, const char *msg, bool miss=false)
void GetTag(Tag &tag) const
Read the requested tag and store it in the user-provided tag instance.
Definition: packet.cc:49
read and write tag data
Definition: tag-buffer.h:51
uint32_t GetStart(void) const
The index is an offset from the start of the packet.
Definition: packet.cc:39
void WriteU8(uint8_t data)
Definition: buffer.h:868
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:831
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
#define ReplaceCheck(n)
static PacketTestSuite g_packetTestSuite
virtual uint32_t Deserialize(Buffer::Iterator iter)
uint8_t ReadU8(void)
Definition: buffer.h:1020
#define RemoveCheck(n)
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:356
std::string GetName(void) const
Definition: test.cc:369
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
virtual void Serialize(Buffer::Iterator iter) const
void DoCheck(Ptr< const Packet > p, const char *file, int line, uint32_t n,...)
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:904
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:257
bool verbose
TypeId HideFromDocumentation(void)
Hide this TypeId from documentation.
Definition: type-id.cc:1117
#define E(a, b, c)
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:791
#define CHECK(p, n,...)
int AddRemoveTime(const bool verbose=false)