1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  *
16  * Author:  Craig Dowell (craigdo@ee.washington.edu)
17  */
18 
19 #include <iostream>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <sstream>
23 #include <cstring>
24 
25 #include "ns3/log.h"
26 #include "ns3/test.h"
27 #include "ns3/pcap-file.h"
28 
29 using namespace ns3;
30 
31 NS_LOG_COMPONENT_DEFINE ("pcap-file-test-suite");
32 
33 // ===========================================================================
34 // Some utility functions for the tests.
35 // ===========================================================================
36 
37 static uint16_t
Swap(uint16_t val)38 Swap (uint16_t val)
39 {
40   return ((val >> 8) & 0x00ff) | ((val << 8) & 0xff00);
41 }
42 
43 static uint32_t
Swap(uint32_t val)44 Swap (uint32_t val)
45 {
46   return ((val >> 24) & 0x000000ff) | ((val >> 8) & 0x0000ff00) | ((val << 8) & 0x00ff0000) | ((val << 24) & 0xff000000);
47 }
48 
49 static bool
CheckFileExists(std::string filename)50 CheckFileExists (std::string filename)
51 {
52   FILE * p = std::fopen (filename.c_str (), "rb");
53   if (p == 0)
54     {
55       return false;
56     }
57 
58   std::fclose (p);
59   return true;
60 }
61 
62 
63 static bool
CheckFileLength(std::string filename,uint64_t sizeExpected)64 CheckFileLength (std::string filename, uint64_t sizeExpected)
65 {
66   FILE * p = std::fopen (filename.c_str (), "rb");
67   if (p == 0)
68     {
69       return false;
70     }
71 
72   std::fseek (p, 0, SEEK_END);
73 
74   uint64_t sizeActual = std::ftell (p);
75   std::fclose (p);
76 
77   return sizeActual == sizeExpected;
78 }
79 
80 /**
81  * \ingroup network-test
82  * \ingroup tests
83  *
84  * \brief Test case to make sure that the Pcap File Object can do its
85  * most basic job and create an empty pcap file.
86  */
87 class WriteModeCreateTestCase : public TestCase
88 {
89 public:
90   WriteModeCreateTestCase ();
91   virtual ~WriteModeCreateTestCase ();
92 
93 private:
94   virtual void DoSetup (void);
95   virtual void DoRun (void);
96   virtual void DoTeardown (void);
97 
98   std::string m_testFilename; //!< File name
99 };
100 
WriteModeCreateTestCase()101 WriteModeCreateTestCase::WriteModeCreateTestCase ()
102   : TestCase ("Check to see that PcapFile::Open with mode std::ios::out works")
103 {
104 }
105 
~WriteModeCreateTestCase()106 WriteModeCreateTestCase::~WriteModeCreateTestCase ()
107 {
108 }
109 
110 void
DoSetup(void)111 WriteModeCreateTestCase::DoSetup (void)
112 {
113   std::stringstream filename;
114   uint32_t n = rand ();
115   filename << n;
116   m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
117 }
118 
119 void
DoTeardown(void)120 WriteModeCreateTestCase::DoTeardown (void)
121 {
122   if (remove (m_testFilename.c_str ()))
123     {
124       NS_LOG_ERROR ("Failed to delete file " << m_testFilename);
125     }
126 }
127 
128 void
DoRun(void)129 WriteModeCreateTestCase::DoRun (void)
130 {
131   PcapFile f;
132 
133   //
134   // Opening a new file in write mode should result in an empty file of the
135   // given name.
136   //
137   f.Open (m_testFilename, std::ios::out);
138 
139   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename << ", \"w\") returns error");
140   f.Close ();
141 
142   NS_TEST_ASSERT_MSG_EQ (CheckFileExists (m_testFilename), true,
143                          "Open (" << m_testFilename << ", \"std::ios::out\") does not create file");
144   NS_TEST_ASSERT_MSG_EQ (CheckFileLength (m_testFilename, 0), true,
145                          "Open (" << m_testFilename << ", \"std::ios::out\") does not result in an empty file");
146 
147   //
148   // Calling Init() on a file created with "std::ios::out" should result in a file just
149   // long enough to contain the pcap file header.
150   //
151   f.Open (m_testFilename, std::ios::out);
152   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
153                          ", \"std::ios::out\") returns error");
154 
155   f.Init (1234, 5678, 7);
156   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
157 
158   f.Close ();
159 
160   NS_TEST_ASSERT_MSG_EQ (CheckFileLength (m_testFilename, 24), true,
161                          "Init () does not result in a file with a pcap file header");
162 
163   //
164   // Opening an existing file in write mode should result in that file being
165   // emptied.
166   //
167   f.Open (m_testFilename, std::ios::out);
168   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
169                          ", \"std::ios::out\") returns error");
170 
171   f.Close ();
172 
173   NS_TEST_ASSERT_MSG_EQ (CheckFileLength (m_testFilename, 0), true,
174                          "Open (" << m_testFilename << ", \"w\") does not result in an empty file");
175 
176   //
177   // Initialize the file again.
178   //
179   f.Open (m_testFilename, std::ios::out);
180   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false,
181                          "Open (" << m_testFilename << ", \"w\") returns error");
182 
183   f.Init (1234, 5678, 7);
184   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
185 
186   //
187   // Now we should be able to write to it since it was opened in std::ios::out mode.
188   // This is just a permissions check so we don't actually look at the
189   // data.
190   //
191   uint8_t buffer[128];
192   memset (buffer, 0, sizeof(buffer));
193   f.Write (0, 0, buffer, 128);
194   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Write (write-only-file " << m_testFilename <<
195                          ") returns error");
196 }
197 
198 /**
199  * \ingroup network-test
200  * \ingroup tests
201  *
202  * \brief Test case to make sure that the Pcap File Object can open an
203  * existing pcap file.
204  */
205 class ReadModeCreateTestCase : public TestCase
206 {
207 public:
208   ReadModeCreateTestCase ();
209   virtual ~ReadModeCreateTestCase ();
210 
211 private:
212   virtual void DoSetup (void);
213   virtual void DoRun (void);
214   virtual void DoTeardown (void);
215 
216   std::string m_testFilename; //!< File name
217 };
218 
ReadModeCreateTestCase()219 ReadModeCreateTestCase::ReadModeCreateTestCase ()
220   : TestCase ("Check to see that PcapFile::Open with mode std::ios::in works")
221 {
222 }
223 
~ReadModeCreateTestCase()224 ReadModeCreateTestCase::~ReadModeCreateTestCase ()
225 {
226 }
227 
228 void
DoSetup(void)229 ReadModeCreateTestCase::DoSetup (void)
230 {
231   std::stringstream filename;
232   uint32_t n = rand ();
233   filename << n;
234   m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
235 }
236 
237 void
DoTeardown(void)238 ReadModeCreateTestCase::DoTeardown (void)
239 {
240   if (remove (m_testFilename.c_str ()))
241     {
242       NS_LOG_ERROR ("Failed to delete file " << m_testFilename);
243     }
244 }
245 
246 void
DoRun(void)247 ReadModeCreateTestCase::DoRun (void)
248 {
249   PcapFile f;
250 
251   //
252   // Opening a non-existing file in read mode should result in an error.
253   //
254   f.Open (m_testFilename, std::ios::in);
255   NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Open (non-existing-filename " << m_testFilename <<
256                          ", \"std::ios::in\") does not return error");
257   f.Close ();
258   f.Clear ();
259   NS_TEST_ASSERT_MSG_EQ (CheckFileExists (m_testFilename), false, "Open (" << m_testFilename <<
260                          ", \"std::ios::in\") unexpectedly created a file");
261 
262   //
263   // Okay, now create an uninitialized file using previously tested operations
264   //
265   f.Open (m_testFilename, std::ios::out);
266   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (filename, \"std::ios::out\") returns error");
267   f.Close ();
268 
269   //
270   // Opening this file should result in an error since it has no pcap file header.
271   //
272   f.Open (m_testFilename, std::ios::in);
273   NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Open (non-initialized-filename " << m_testFilename <<
274                          ", \"std::ios::in\") does not return error");
275   f.Close ();
276   f.Clear ();
277 
278   //
279   // Okay, now open that non-initialized file in write mode and initialize it
280   // Note that we open it in write mode to initialize it.
281   //
282   f.Open (m_testFilename, std::ios::out);
283   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
284                          ", \"std::ios::out\") returns error");
285 
286   f.Init (1234, 5678, 7);
287   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
288   f.Close ();
289 
290   //
291   // Opening this file should now work since it has a pcap file header.
292   //
293   f.Open (m_testFilename, std::ios::in);
294   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (initialized-filename " << m_testFilename <<
295                          ", \"std::ios::in\") returns error");
296 
297   //
298   // Now we should not be able to write to it since it was opened in "r" mode
299   // even if it has been initialized..
300   //
301   uint8_t buffer[128];
302   f.Write (0, 0, buffer, 128);
303   NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Write (read-only-file " << m_testFilename <<
304                          ") does not return error");
305   f.Close ();
306   f.Clear ();
307 }
308 
309 #if 0
310 // ===========================================================================
311 // Test case to make sure that the Pcap File Object can open an existing pcap
312 // file for appending.
313 // ===========================================================================
314 class AppendModeCreateTestCase : public TestCase
315 {
316 public:
317   AppendModeCreateTestCase ();
318   virtual ~AppendModeCreateTestCase ();
319 
320 private:
321   virtual void DoSetup (void);
322   virtual void DoRun (void);
323   virtual void DoTeardown (void);
324 
325   std::string m_testFilename;
326 };
327 
328 AppendModeCreateTestCase::AppendModeCreateTestCase ()
329   : TestCase ("Check to see that PcapFile::Open with mode std::ios::app works")
330 {
331 }
332 
333 AppendModeCreateTestCase::~AppendModeCreateTestCase ()
334 {
335 }
336 
337 void
338 AppendModeCreateTestCase::DoSetup (void)
339 {
340   std::stringstream filename;
341   uint32_t n = rand ();
342   filename << n;
343   m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
344 }
345 
346 void
347 AppendModeCreateTestCase::DoTeardown (void)
348 {
349   if (remove (m_testFilename.c_str ()))
350     {
351       NS_LOG_ERROR ("Failed to delete file " << m_testFilename);
352     }
353 }
354 
355 void
356 AppendModeCreateTestCase::DoRun (void)
357 {
358   PcapFile f;
359 
360   //
361   // Opening a non-existing file in append mode should result in an error.
362   //
363   f.Open (m_testFilename, std::ios::out | std::ios::app);
364   NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Open (non-existing-filename " << m_testFilename <<
365                          ", \"std::ios::app\") does not return error");
366   f.Close ();
367   f.Clear ();
368 
369   NS_TEST_ASSERT_MSG_EQ (CheckFileExists (m_testFilename), false,
370                          "Open (" << m_testFilename << ", \"std::ios::app\") unexpectedly created a file");
371 
372   //
373   // Okay, now create an uninitialized file using previously tested operations
374   //
375   f.Open (m_testFilename, std::ios::out);
376   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
377                          ", \"std::ios::out\") returns error");
378   f.Close ();
379 
380   //
381   // Opening this file should result in an error since it has no pcap file header.
382   //
383   f.Open (m_testFilename, std::ios::out | std::ios::app);
384   NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Open (non-initialized-filename " << m_testFilename <<
385                          ", \"std::ios::app\") does not return error");
386   f.Close ();
387   f.Clear ();
388 
389   //
390   // Okay, now open that non-initialized file in write mode and initialize it.
391   //
392   f.Open (m_testFilename, std::ios::out);
393   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (non-initialized-filename " << m_testFilename <<
394                          ", \"std::ios::out\") returns error");
395 
396   f.Init (1234, 5678, 7);
397   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
398   f.Close ();
399 
400   //
401   // Opening this file should now work since it has a pcap file header.
402   //
403   f.Open (m_testFilename, std::ios::out | std::ios::app);
404   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (initialized-filename " << m_testFilename <<
405                          ", \"std::ios::app\") returns error");
406 
407   //
408   // We should be able to write to it since it was opened in "std::ios::app" mode.
409   //
410   uint8_t buffer[128];
411   memset (buffer, 0, sizeof(buffer));
412   f.Write (0, 0, buffer, 128);
413   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Write (append-mode-file " << m_testFilename << ") returns error");
414 
415   f.Close ();
416 }
417 #endif
418 
419 /**
420  * \ingroup network-test
421  * \ingroup tests
422  *
423  * \brief Test case to make sure that the Pcap File Object can
424  * write out correct pcap file headers in both endian cases,
425  * and then read them in correctly.
426  */
427 class FileHeaderTestCase : public TestCase
428 {
429 public:
430   FileHeaderTestCase ();
431   virtual ~FileHeaderTestCase ();
432 
433 private:
434   virtual void DoSetup (void);
435   virtual void DoRun (void);
436   virtual void DoTeardown (void);
437 
438   std::string m_testFilename; //!< File name
439 };
440 
FileHeaderTestCase()441 FileHeaderTestCase::FileHeaderTestCase ()
442   : TestCase ("Check to see that PcapFileHeader is managed correctly")
443 {
444 }
445 
~FileHeaderTestCase()446 FileHeaderTestCase::~FileHeaderTestCase ()
447 {
448 }
449 
450 void
DoSetup(void)451 FileHeaderTestCase::DoSetup (void)
452 {
453   std::stringstream filename;
454   uint32_t n = rand ();
455   filename << n;
456   m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
457 }
458 
459 void
DoTeardown(void)460 FileHeaderTestCase::DoTeardown (void)
461 {
462   if (remove (m_testFilename.c_str ()))
463     {
464       NS_LOG_ERROR ("Failed to delete file " << m_testFilename);
465     }
466 }
467 
468 void
DoRun(void)469 FileHeaderTestCase::DoRun (void)
470 {
471   PcapFile f;
472 
473   //
474   // Create an uninitialized file using previously tested operations
475   //
476   f.Open (m_testFilename, std::ios::out);
477   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
478                          ", \"std::ios::out\") returns error");
479 
480   //
481   // Initialize the pcap file header.
482   //
483   f.Init (1234, 5678, 7);
484   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false,
485                          "Init (1234, 5678, 7) returns error");
486   f.Close ();
487 
488   //
489   // Take a look and see what was done to the file
490   //
491   FILE *p = std::fopen (m_testFilename.c_str (), "r+b");
492   NS_TEST_ASSERT_MSG_NE (p, 0, "fopen(" << m_testFilename << ") should have been able to open a correctly created pcap file");
493 
494   uint32_t val32;
495   uint16_t val16;
496 
497   //
498   // Because the regression tests require that pcap file output be compared
499   // byte-by-byte, we had to decide on a single format for written pcap files.
500   // This was little endian.  So we have to do something special with big-
501   // endian machines here.
502   //
503   // When a big endian machine writes a pcap file, it is forced into swap
504   // mode and actually writes little endian files.  This is automagically
505   // fixed up when using a PcapFile to read the values, but when a big-
506   // endian machine reads these values directly, they will be swapped.
507   //
508   // We can remove this nonsense when we get rid of the pcap-file-comparison
509   // regression tests.
510   //
511   // So, determine the endian-ness of the running system, and if we're on
512   // a big-endian machine, swap all of the results below before checking.
513   //
514   union {
515     uint32_t a;
516     uint8_t  b[4];
517   } u;
518 
519   u.a = 1;
520   bool bigEndian = u.b[3];
521 
522   size_t result = std::fread (&val32, sizeof(val32), 1, p);
523   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() magic number");
524   if (bigEndian) val32 = Swap (val32);
525   NS_TEST_ASSERT_MSG_EQ (val32, 0xa1b2c3d4, "Magic number written incorrectly");
526 
527   result = std::fread (&val16, sizeof(val16), 1, p);
528   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() version major");
529   if (bigEndian) val16 = Swap (val16);
530   NS_TEST_ASSERT_MSG_EQ (val16, 2, "Version major written incorrectly");
531 
532   result = std::fread (&val16, sizeof(val16), 1, p);
533   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() version minor");
534   if (bigEndian) val16 = Swap (val16);
535   NS_TEST_ASSERT_MSG_EQ (val16, 4, "Version minor written incorrectly");
536 
537   result = std::fread (&val32, sizeof(val32), 1, p);
538   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() time zone correction");
539   if (bigEndian) val32 = Swap (val32);
540   NS_TEST_ASSERT_MSG_EQ (val32, 7, "Version minor written incorrectly");
541 
542   result = std::fread (&val32, sizeof(val32), 1, p);
543   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() sig figs");
544   if (bigEndian) val32 = Swap (val32);
545   NS_TEST_ASSERT_MSG_EQ (val32, 0, "Sig figs written incorrectly");
546 
547   result = std::fread (&val32, sizeof(val32), 1, p);
548   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() snap length");
549   if (bigEndian) val32 = Swap (val32);
550   NS_TEST_ASSERT_MSG_EQ (val32, 5678, "Snap length written incorrectly");
551 
552   result = std::fread (&val32, sizeof(val32), 1, p);
553   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() data link type");
554   if (bigEndian) val32 = Swap (val32);
555   NS_TEST_ASSERT_MSG_EQ (val32, 1234, "Data length type written incorrectly");
556 
557   std::fclose (p);
558   p = 0;
559 
560   //
561   // We wrote a little-endian file out correctly, now let's see if we can read
562   // it back in correctly.
563   //
564   // As mentioned above, when a big endian machine writes a pcap file, it is
565   // forced into swap mode and actually writes little endian files.  This is
566   // automagically fixed up when using a PcapFile to read the values, so we
567   // don't have to do anything special here.
568   //
569   f.Open (m_testFilename, std::ios::in);
570   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (existing-initialized-file " << m_testFilename <<
571                          ", \"std::ios::in\") returns error");
572 
573   NS_TEST_ASSERT_MSG_EQ (f.GetMagic (), 0xa1b2c3d4, "Read back magic number incorrectly");
574   NS_TEST_ASSERT_MSG_EQ (f.GetVersionMajor (), 2, "Read back version major incorrectly");
575   NS_TEST_ASSERT_MSG_EQ (f.GetVersionMinor (), 4, "Read back version minor incorrectly");
576   NS_TEST_ASSERT_MSG_EQ (f.GetTimeZoneOffset (), 7, "Read back time zone offset incorrectly");
577   NS_TEST_ASSERT_MSG_EQ (f.GetSigFigs (), 0, "Read back sig figs incorrectly");
578   NS_TEST_ASSERT_MSG_EQ (f.GetSnapLen (), 5678, "Read back snap len incorrectly");
579   NS_TEST_ASSERT_MSG_EQ (f.GetDataLinkType (), 1234, "Read back data link type incorrectly");
580   f.Close ();
581 
582   //
583   // Re-open the file to erase its contents.
584   //
585   f.Open (m_testFilename, std::ios::out);
586   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
587                          ", \"std::ios::out\") returns error");
588 
589   //
590   // Initialize the pcap file header, turning on swap mode manually to force
591   // the pcap file header to be written out in foreign-endian form, whichever
592   // endian-ness that might be.  Since big-endian machines are automatically
593   // forced into swap mode, the <true> parameter to f.Init() below is actually
594   // a no-op and we're always writing foreign-endian files.  In that case,
595   // this test case is really just a duplicate of the previous.
596   //
597   f.Init (1234, 5678, 7, true);
598   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
599   f.Close ();
600 
601   //
602   // Take a look and see what was done to the file.  Everything should now
603   // appear byte-swapped.
604   //
605   p = std::fopen (m_testFilename.c_str (), "r+b");
606   NS_TEST_ASSERT_MSG_NE (p, 0, "fopen(" << m_testFilename << ") should have been able to open a correctly created pcap file");
607 
608   result = std::fread (&val32, sizeof(val32), 1, p);
609   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() magic number");
610   NS_TEST_ASSERT_MSG_EQ (val32, Swap (uint32_t (0xa1b2c3d4)), "Magic number written incorrectly");
611 
612   result = std::fread (&val16, sizeof(val16), 1, p);
613   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() version major");
614   NS_TEST_ASSERT_MSG_EQ (val16, Swap (uint16_t (2)), "Version major written incorrectly");
615 
616   result = std::fread (&val16, sizeof(val16), 1, p);
617   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() version minor");
618   NS_TEST_ASSERT_MSG_EQ (val16, Swap (uint16_t (4)), "Version minor written incorrectly");
619 
620   result = std::fread (&val32, sizeof(val32), 1, p);
621   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() time zone correction");
622   NS_TEST_ASSERT_MSG_EQ (val32, Swap (uint32_t (7)), "Version minor written incorrectly");
623 
624   result = std::fread (&val32, sizeof(val32), 1, p);
625   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() sig figs");
626   NS_TEST_ASSERT_MSG_EQ (val32, 0, "Sig figs written incorrectly");
627 
628   result = std::fread (&val32, sizeof(val32), 1, p);
629   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() snap length");
630   NS_TEST_ASSERT_MSG_EQ (val32, Swap (uint32_t (5678)), "Snap length written incorrectly");
631 
632   result = std::fread (&val32, sizeof(val32), 1, p);
633   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() data link type");
634   NS_TEST_ASSERT_MSG_EQ (val32, Swap (uint32_t (1234)), "Data length type written incorrectly");
635 
636   std::fclose (p);
637   p = 0;
638 
639   //
640   // We wrote an opposite-endian file out correctly, now let's see if we can read
641   // it back in correctly.  Again, in the case of a big-endian machine, we already
642   // did this test and it is just a duplicate.  What we don't test on a big endian
643   // machine is writing out a big-endian file by default, but we can't do that
644   // since it breaks regression testing.
645   //
646   f.Open (m_testFilename, std::ios::in);
647   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (existing-initialized-file " << m_testFilename <<
648                          ", \"std::ios::in\") returns error");
649 
650   NS_TEST_ASSERT_MSG_EQ (f.GetSwapMode (), true, "Byte-swapped file not correctly indicated");
651 
652   NS_TEST_ASSERT_MSG_EQ (f.GetMagic (), 0xa1b2c3d4, "Read back magic number incorrectly");
653   NS_TEST_ASSERT_MSG_EQ (f.GetVersionMajor (), 2, "Read back version major incorrectly");
654   NS_TEST_ASSERT_MSG_EQ (f.GetVersionMinor (), 4, "Read back version minor incorrectly");
655   NS_TEST_ASSERT_MSG_EQ (f.GetTimeZoneOffset (), 7, "Read back time zone offset incorrectly");
656   NS_TEST_ASSERT_MSG_EQ (f.GetSigFigs (), 0, "Read back sig figs incorrectly");
657   NS_TEST_ASSERT_MSG_EQ (f.GetSnapLen (), 5678, "Read back snap len incorrectly");
658   NS_TEST_ASSERT_MSG_EQ (f.GetDataLinkType (), 1234, "Read back data link type incorrectly");
659 
660   f.Close ();
661 }
662 
663 /**
664  * \ingroup network-test
665  * \ingroup tests
666  *
667  * \brief Test case to make sure that the Pcap File Object can
668  * write pcap packet records in both endian cases, and then read
669  * them in correctly.
670  */
671 class RecordHeaderTestCase : public TestCase
672 {
673 public:
674   RecordHeaderTestCase ();
675   virtual ~RecordHeaderTestCase ();
676 
677 private:
678   virtual void DoSetup (void);
679   virtual void DoRun (void);
680   virtual void DoTeardown (void);
681 
682   std::string m_testFilename; //!< File name
683 };
684 
RecordHeaderTestCase()685 RecordHeaderTestCase::RecordHeaderTestCase ()
686   : TestCase ("Check to see that PcapRecordHeader is managed correctly")
687 {
688 }
689 
~RecordHeaderTestCase()690 RecordHeaderTestCase::~RecordHeaderTestCase ()
691 {
692 }
693 
694 void
DoSetup(void)695 RecordHeaderTestCase::DoSetup (void)
696 {
697   std::stringstream filename;
698   uint32_t n = rand ();
699   filename << n;
700   m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
701 }
702 
703 void
DoTeardown(void)704 RecordHeaderTestCase::DoTeardown (void)
705 {
706   if (remove (m_testFilename.c_str ()))
707     {
708       NS_LOG_ERROR ("Failed to delete file " << m_testFilename);
709     }
710 }
711 
712 void
DoRun(void)713 RecordHeaderTestCase::DoRun (void)
714 {
715   PcapFile f;
716 
717   //
718   // Create an uninitialized file using previously tested operations
719   //
720   f.Open (m_testFilename, std::ios::out);
721   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
722                          ", \"std::ios::out\") returns error");
723 
724   //
725   // Initialize the pcap file header.
726   //
727   f.Init (37, 43, -7);
728   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (37, 43, -7) returns error");
729 
730   //
731   // Initialize a buffer with a counting pattern to check the data later.
732   //
733   uint8_t bufferOut[128];
734   for (uint32_t i = 0; i < 128; ++i)
735     {
736       bufferOut[i] = i;
737     }
738 
739   //
740   // Now we should be able to write a packet to it since it was opened in "w"
741   // mode.  The packet data written should be limited to 43 bytes in length
742   // by the Init() call above.
743   //
744   f.Write (1234, 5678, bufferOut, 128);
745   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Write (write-only-file " << m_testFilename << ") returns error");
746   f.Close ();
747 
748   //
749   // Let's peek into the file and see what actually went out for that
750   // packet.
751   //
752   FILE *p = std::fopen (m_testFilename.c_str (), "r+b");
753   NS_TEST_ASSERT_MSG_NE (p, 0, "fopen() should have been able to open a correctly created pcap file");
754 
755   //
756   // A pcap file header takes up 24 bytes, a pcap record header takes up 16 bytes
757   // and we wrote in 43 bytes, so the file must be 83 bytes long.  Let's just
758   // double check that this is exactly what happened.
759   //
760   std::fseek (p, 0, SEEK_END);
761   uint64_t size = std::ftell (p);
762   NS_TEST_ASSERT_MSG_EQ (size, 83, "Pcap file with one 43 byte packet is incorrect size");
763 
764   //
765   // A pcap file header takes up 24 bytes, so we should see a pcap record header
766   // starting there in the file.  We've tested this all before so we just assume
767   // it's all right and just seek to just past that point..
768   //
769   std::fseek (p, 24, SEEK_SET);
770 
771   uint32_t val32;
772 
773   //
774   // Because the regression tests require that pcap file output be compared
775   // byte-by-byte, we had to decide on a single format for written pcap files.
776   // This was little endian.  So we have to do something special with big-
777   // endian machines here.
778   //
779   // When a big endian machine writes a pcap file, it is forced into swap
780   // mode and actually writes little endian files.  This is automagically
781   // fixed up when using a PcapFile to read the values, but when a big-
782   // endian machine reads these values directly, they will be swapped.
783   //
784   // We can remove this nonsense when we get rid of the pcap-file-comparison
785   // regression tests.
786   //
787   // So, determine the endian-ness of the running system, and if we're on
788   // a big-endian machine, swap all of the results below before checking.
789   //
790   union {
791     uint32_t a;
792     uint8_t  b[4];
793   } u;
794 
795   u.a = 1;
796   bool bigEndian = u.b[3];
797 
798   size_t result = std::fread (&val32, sizeof(val32), 1, p);
799   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() seconds timestamp");
800   if (bigEndian) val32 = Swap (val32);
801   NS_TEST_ASSERT_MSG_EQ (val32, 1234, "Seconds timestamp written incorrectly");
802 
803   result = std::fread (&val32, sizeof(val32), 1, p);
804   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() microseconds timestamp");
805   if (bigEndian) val32 = Swap (val32);
806   NS_TEST_ASSERT_MSG_EQ (val32, 5678, "Microseconds timestamp written incorrectly");
807 
808   result = std::fread (&val32, sizeof(val32), 1, p);
809   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() included length");
810   if (bigEndian) val32 = Swap (val32);
811   NS_TEST_ASSERT_MSG_EQ (val32, 43, "Included length written incorrectly");
812 
813   result = std::fread (&val32, sizeof(val32), 1, p);
814   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() actual length");
815   if (bigEndian) val32 = Swap (val32);
816   NS_TEST_ASSERT_MSG_EQ (val32, 128, "Actual length written incorrectly");
817 
818   //
819   // Take a look and see what went out into the file.  The packet data
820   // should be unchanged (unswapped).
821   //
822   uint8_t bufferIn[128];
823 
824   result = std::fread (bufferIn, 1, 43, p);
825   NS_TEST_ASSERT_MSG_EQ (result, 43, "Unable to fread() packet data of expected length");
826 
827   for (uint32_t i = 0; i < 43; ++i)
828     {
829       NS_TEST_ASSERT_MSG_EQ (bufferIn[i], bufferOut[i], "Incorrect packet data written");
830     }
831 
832   std::fclose (p);
833   p = 0;
834 
835   //
836   // Let's see if the PcapFile object can figure out how to do the same thing and
837   // correctly read in a packet.
838   //
839   f.Open (m_testFilename, std::ios::in);
840   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
841                          ", \"std::ios::in\") of existing good file returns error");
842 
843   uint32_t tsSec, tsUsec, inclLen, origLen, readLen;
844 
845   f.Read (bufferIn, sizeof(bufferIn), tsSec, tsUsec, inclLen, origLen, readLen);
846   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Read() of known good packet returns error");
847   NS_TEST_ASSERT_MSG_EQ (tsSec, 1234, "Incorrectly read seconds timestamp from known good packet");
848   NS_TEST_ASSERT_MSG_EQ (tsUsec, 5678, "Incorrectly read microseconds timestamp from known good packet");
849   NS_TEST_ASSERT_MSG_EQ (inclLen, 43, "Incorrectly read included length from known good packet");
850   NS_TEST_ASSERT_MSG_EQ (origLen, 128, "Incorrectly read original length from known good packet");
851   NS_TEST_ASSERT_MSG_EQ (readLen, 43, "Incorrectly constructed actual read length from known good packet given buffer size");
852   f.Close ();
853 
854   //
855   // Did the data come back correctly?
856   //
857   for (uint32_t i = 0; i < 43; ++i)
858     {
859       NS_TEST_ASSERT_MSG_EQ (bufferIn[i], bufferOut[i], "Incorrect packet data read from known good packet");
860     }
861 
862   //
863   // We have to check to make sure that the pcap record header is swapped
864   // correctly.  Since big-endian machines are automatically forced into
865   // swap mode, the <true> parameter to f.Init() below is actually
866   // a no-op and we're always writing foreign-endian files.  In that case,
867   // this test case is really just a duplicate of the previous.
868   //
869   // Open the file in write mode to clear the data.
870   //
871   f.Open (m_testFilename, std::ios::out);
872   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
873                          ", \"std::ios::out\") returns error");
874 
875   //
876   // Initialize the pcap file header, forcing the object into swap mode.
877   //
878   f.Init (37, 43, -7, true);
879   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (37, 43, -7) returns error");
880 
881   //
882   // Now we should be able to write a packet to it since it was opened in "w"
883   // mode.  The packet data written should be limited to 43 bytes in length
884   // by the Init() call above.
885   //
886   f.Write (1234, 5678, bufferOut, 128);
887   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Write (write-only-file " << m_testFilename << ") returns error");
888   f.Close ();
889 
890   //
891   // Let's peek into the file and see what actually went out for that
892   // packet.
893   //
894   p = std::fopen (m_testFilename.c_str (), "r+b");
895   NS_TEST_ASSERT_MSG_NE (p, 0, "fopen() should have been able to open a correctly created pcap file");
896 
897   //
898   // A pcap file header takes up 24 bytes, a pcap record header takes up 16 bytes
899   // and we wrote in 43 bytes, so the file must be 83 bytes long.  Let's just
900   // double check that this is exactly what happened.
901   //
902   std::fseek (p, 0, SEEK_END);
903   size = std::ftell (p);
904   NS_TEST_ASSERT_MSG_EQ (size, 83, "Pcap file with one 43 byte packet is incorrect size");
905 
906   //
907   // A pcap file header takes up 24 bytes, so we should see a pcap record header
908   // starting there in the file.  We've tested this all before so we just assume
909   // it's all right and just seek past it.
910   //
911   result = std::fseek (p, 24, SEEK_SET);
912   NS_TEST_ASSERT_MSG_EQ (result, 0, "Failed seeking past pcap header");
913 
914   result = std::fread (&val32, sizeof(val32), 1, p);
915   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() seconds timestamp");
916   NS_TEST_ASSERT_MSG_EQ (val32, Swap (uint32_t (1234)), "Swapped seconds timestamp written incorrectly");
917 
918   result = std::fread (&val32, sizeof(val32), 1, p);
919   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() microseconds timestamp");
920   NS_TEST_ASSERT_MSG_EQ (val32, Swap (uint32_t (5678)), "Swapped microseconds timestamp written incorrectly");
921 
922   result = std::fread (&val32, sizeof(val32), 1, p);
923   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() included length");
924   NS_TEST_ASSERT_MSG_EQ (val32, Swap (uint32_t (43)), "Swapped included length written incorrectly");
925 
926   result = std::fread (&val32, sizeof(val32), 1, p);
927   NS_TEST_ASSERT_MSG_EQ (result, 1, "Unable to fread() actual length");
928   NS_TEST_ASSERT_MSG_EQ (val32, Swap (uint32_t (128)), "Swapped Actual length written incorrectly");
929 
930   //
931   // Take a look and see what went out into the file.  The packet data
932   // should be unchanged (unswapped).
933   //
934   result = std::fread (bufferIn, 1, 43, p);
935   NS_TEST_ASSERT_MSG_EQ (result, 43, "Unable to fread() packet data of expected length");
936 
937   for (uint32_t i = 0; i < 43; ++i)
938     {
939       NS_TEST_ASSERT_MSG_EQ (bufferIn[i], bufferOut[i], "Incorrect packet data written");
940     }
941 
942   std::fclose (p);
943   p = 0;
944 
945   //
946   // Let's see if the PcapFile object can figure out how to do the same thing and
947   // correctly read in a packet.  The record header info should come back to us
948   // swapped back into correct form.
949   //
950   f.Open (m_testFilename, std::ios::in);
951   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
952                          ", \"std::ios::in\") of existing good file returns error");
953 
954   f.Read (bufferIn, sizeof(bufferIn), tsSec, tsUsec, inclLen, origLen, readLen);
955   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Read() of known good packet returns error");
956   NS_TEST_ASSERT_MSG_EQ (tsSec, 1234, "Incorrectly read seconds timestamp from known good packet");
957   NS_TEST_ASSERT_MSG_EQ (tsUsec, 5678, "Incorrectly read microseconds timestamp from known good packet");
958   NS_TEST_ASSERT_MSG_EQ (inclLen, 43, "Incorrectly read included length from known good packet");
959   NS_TEST_ASSERT_MSG_EQ (origLen, 128, "Incorrectly read original length from known good packet");
960   NS_TEST_ASSERT_MSG_EQ (readLen, 43, "Incorrectly constructed actual read length from known good packet given buffer size");
961 
962   //
963   // Did the data come back correctly (unchanged / unswapped)?
964   //
965   for (uint32_t i = 0; i < 43; ++i)
966     {
967       NS_TEST_ASSERT_MSG_EQ (bufferIn[i], bufferOut[i], "Incorrect packet data read from known good packet");
968     }
969 
970   f.Close ();
971 }
972 
973 /**
974  * \ingroup network-test
975  * \ingroup tests
976  *
977  * \brief Test case to make sure that the Pcap File Object can read
978  * out the contents of a known good pcap file.
979  */
980 class ReadFileTestCase : public TestCase
981 {
982 public:
983   ReadFileTestCase ();
984   virtual ~ReadFileTestCase ();
985 
986 private:
987   virtual void DoSetup (void);
988   virtual void DoRun (void);
989   virtual void DoTeardown (void);
990 
991   std::string m_testFilename; //!< File name
992 };
993 
ReadFileTestCase()994 ReadFileTestCase::ReadFileTestCase ()
995   : TestCase ("Check to see that PcapFile can read out a known good pcap file")
996 {
997 }
998 
~ReadFileTestCase()999 ReadFileTestCase::~ReadFileTestCase ()
1000 {
1001 }
1002 
1003 void
DoSetup(void)1004 ReadFileTestCase::DoSetup (void)
1005 {
1006 }
1007 
1008 void
DoTeardown(void)1009 ReadFileTestCase::DoTeardown (void)
1010 {
1011 }
1012 
1013 static const uint32_t N_KNOWN_PACKETS = 6;
1014 static const uint32_t N_PACKET_BYTES = 16;
1015 
1016 /**
1017  * PCAP Packet structure
1018  */
1019 typedef struct PACKET_ENTRY {
1020   uint32_t tsSec;   //!< Time (seconds part)
1021   uint32_t tsUsec;  //!< Time (micro seconds part)
1022   uint32_t inclLen; //!< Length of the entry in the PCAP
1023   uint32_t origLen; //!< length of the original packet
1024   uint16_t data[N_PACKET_BYTES];  //!< Packet data
1025 } PacketEntry;
1026 
1027 static const PacketEntry knownPackets[] = {
1028   { 2, 3696,   46,   46, { 0x0001, 0x0800, 0x0604, 0x0001, 0x0000, 0x0000, 0x0003, 0x0a01,
1029                            0x0201, 0xffff, 0xffff, 0xffff, 0x0a01, 0x0204, 0x0000, 0x0000}},
1030   { 2, 3707,   46,   46, { 0x0001, 0x0800, 0x0604, 0x0002, 0x0000, 0x0000, 0x0006, 0x0a01,
1031                            0x0204, 0x0000, 0x0000, 0x0003, 0x0a01, 0x0201, 0x0000, 0x0000}},
1032   { 2, 3801, 1070, 1070, { 0x4500, 0x041c, 0x0000, 0x0000, 0x3f11, 0x0000, 0x0a01, 0x0101,
1033                            0x0a01, 0x0204, 0xc001, 0x0009, 0x0408, 0x0000, 0x0000, 0x0000}},
1034   { 2, 3811,   46,   46, { 0x0001, 0x0800, 0x0604, 0x0001, 0x0000, 0x0000, 0x0006, 0x0a01,
1035                            0x0204, 0xffff, 0xffff, 0xffff, 0x0a01, 0x0201, 0x0000, 0x0000}},
1036   { 2, 3822,   46,   46, { 0x0001, 0x0800, 0x0604, 0x0002, 0x0000, 0x0000, 0x0003, 0x0a01,
1037                            0x0201, 0x0000, 0x0000, 0x0006, 0x0a01, 0x0204, 0x0000, 0x0000}},
1038   { 2, 3915, 1070, 1070, { 0x4500, 0x041c, 0x0000, 0x0000, 0x4011, 0x0000, 0x0a01, 0x0204,
1039                            0x0a01, 0x0101, 0x0009, 0xc001, 0x0408, 0x0000, 0x0000, 0x0000}}
1040 };
1041 
1042 
1043 void
DoRun(void)1044 ReadFileTestCase::DoRun (void)
1045 {
1046   PcapFile f;
1047 
1048   //
1049   //
1050   std::string filename = CreateDataDirFilename ("known.pcap");
1051   f.Open (filename, std::ios::in);
1052   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << filename <<
1053                          ", \"std::ios::in\") returns error");
1054 
1055   //
1056   // We are going to read out the file header and all of the packets to make
1057   // sure that we read what we know, a priori, to be there.
1058   //
1059   // The packet data was gotten using "tcpdump -nn -tt -r known.pcap -x"
1060   // and the timestamp and first 32 bytes of the resulting dump were
1061   // duplicated in the structure above.
1062   //
1063   uint8_t data[N_PACKET_BYTES];
1064   uint32_t tsSec, tsUsec, inclLen, origLen, readLen;
1065 
1066   for (uint32_t i = 0; i < N_KNOWN_PACKETS; ++i)
1067     {
1068       PacketEntry const & p = knownPackets[i];
1069 
1070       f.Read (data, sizeof(data), tsSec, tsUsec, inclLen, origLen, readLen);
1071       NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Read() of known good pcap file returns error");
1072       NS_TEST_ASSERT_MSG_EQ (tsSec, p.tsSec, "Incorrectly read seconds timestap from known good pcap file");
1073       NS_TEST_ASSERT_MSG_EQ (tsUsec, p.tsUsec, "Incorrectly read microseconds timestap from known good pcap file");
1074       NS_TEST_ASSERT_MSG_EQ (inclLen, p.inclLen, "Incorrectly read included length from known good packet");
1075       NS_TEST_ASSERT_MSG_EQ (origLen, p.origLen, "Incorrectly read original length from known good packet");
1076       NS_TEST_ASSERT_MSG_EQ (readLen, N_PACKET_BYTES, "Incorrect actual read length from known good packet given buffer size");
1077     }
1078 
1079   //
1080   // The file should now be at EOF since we've read all of the packets.
1081   // Another packet read should return an error.
1082   //
1083   f.Read (data, 1, tsSec, tsUsec, inclLen, origLen, readLen);
1084   NS_TEST_ASSERT_MSG_EQ (f.Eof (), true, "Read() of known good pcap file at EOF does not return error");
1085 
1086   f.Close ();
1087 }
1088 
1089 /**
1090  * \ingroup network-test
1091  * \ingroup tests
1092  *
1093  * \brief Test case to make sure that the Pcap::Diff method works as expected.
1094  */
1095 class DiffTestCase : public TestCase
1096 {
1097 public:
1098   DiffTestCase ();
1099 
1100 private:
1101   virtual void DoRun (void);
1102 };
1103 
DiffTestCase()1104 DiffTestCase::DiffTestCase ()
1105   : TestCase ("Check that PcapFile::Diff works as expected")
1106 {
1107 }
1108 
1109 void
DoRun(void)1110 DiffTestCase::DoRun (void)
1111 {
1112   //
1113   // Check that PcapDiff(file, file) is false
1114   //
1115   std::string filename = CreateDataDirFilename ("known.pcap");
1116   uint32_t sec (0), usec (0), packets (0);
1117   bool diff = PcapFile::Diff (filename, filename, sec, usec, packets);
1118   NS_TEST_EXPECT_MSG_EQ (diff, false, "PcapDiff(file, file) must always be false");
1119 
1120   //
1121   // Create different PCAP file (with the same timestamps, but different packets) and check that it is indeed different
1122   //
1123   std::string filename2 = CreateTempDirFilename ("different.pcap");
1124   PcapFile f;
1125 
1126   f.Open (filename2, std::ios::out);
1127   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << filename2 << ", \"std::ios::out\") returns error");
1128   f.Init (1, N_PACKET_BYTES);
1129   NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1, " << N_PACKET_BYTES << ") returns error");
1130 
1131   for (uint32_t i = 0; i < N_KNOWN_PACKETS; ++i)
1132     {
1133       PacketEntry const & p = knownPackets[i];
1134 
1135       f.Write (p.tsSec, p.tsUsec, (uint8_t const *)p.data, p.origLen);
1136       NS_TEST_EXPECT_MSG_EQ (f.Fail (), false, "Write must not fail");
1137     }
1138   f.Close ();
1139 
1140   packets = 0;
1141   diff = PcapFile::Diff (filename, filename2, sec, usec, packets);
1142   NS_TEST_EXPECT_MSG_EQ (diff, true, "PcapDiff(file, file2) must be true");
1143   NS_TEST_EXPECT_MSG_EQ (sec,  2, "Files are different from 2.3696 seconds");
1144   NS_TEST_EXPECT_MSG_EQ (usec, 3696, "Files are different from 2.3696 seconds");
1145 }
1146 
1147 /**
1148  * \ingroup network-test
1149  * \ingroup tests
1150  *
1151  * \brief PCAP file utils TestSuite
1152  */
1153 class PcapFileTestSuite : public TestSuite
1154 {
1155 public:
1156   PcapFileTestSuite ();
1157 };
1158 
PcapFileTestSuite()1159 PcapFileTestSuite::PcapFileTestSuite ()
1160   : TestSuite ("pcap-file", UNIT)
1161 {
1162   SetDataDir (NS_TEST_SOURCEDIR);
1163   AddTestCase (new WriteModeCreateTestCase, TestCase::QUICK);
1164   AddTestCase (new ReadModeCreateTestCase, TestCase::QUICK);
1165   //AddTestCase (new AppendModeCreateTestCase, TestCase::QUICK);
1166   AddTestCase (new FileHeaderTestCase, TestCase::QUICK);
1167   AddTestCase (new RecordHeaderTestCase, TestCase::QUICK);
1168   AddTestCase (new ReadFileTestCase, TestCase::QUICK);
1169   AddTestCase (new DiffTestCase, TestCase::QUICK);
1170 }
1171 
1172 static PcapFileTestSuite pcapFileTestSuite; //!< Static variable for test initialization
1173