View | Details | Raw Unified | Return to bug 1001
Collapse All | Expand All

(-)a/src/aodv/test/aodv-regression.cc (-15 / +5 lines)
 Lines 41-51    Link Here 
41
#include "ns3/v4ping-helper.h"
41
#include "ns3/v4ping-helper.h"
42
#include "ns3/nqos-wifi-mac-helper.h"
42
#include "ns3/nqos-wifi-mac-helper.h"
43
#include "ns3/config.h"
43
#include "ns3/config.h"
44
#include "ns3/pcap-test.h"
44
#include <sstream>
45
#include <sstream>
45
46
46
/// Set to true to rewrite reference traces, leave false to run regression tests
47
const bool WRITE_VECTORS = false;
48
49
namespace ns3 {
47
namespace ns3 {
50
namespace aodv {
48
namespace aodv {
51
//-----------------------------------------------------------------------------
49
//-----------------------------------------------------------------------------
 Lines 56-61    Link Here 
56
public:
54
public:
57
  AodvRegressionTestSuite () : TestSuite ("routing-aodv-regression", SYSTEM) 
55
  AodvRegressionTestSuite () : TestSuite ("routing-aodv-regression", SYSTEM) 
58
  {
56
  {
57
    SetDataDir (NS_TEST_SOURCEDIR);
59
    // General RREQ-RREP-RRER test case
58
    // General RREQ-RREP-RRER test case
60
    AddTestCase (new ChainRegressionTest ("aodv-chain-regression-test"));
59
    AddTestCase (new ChainRegressionTest ("aodv-chain-regression-test"));
61
    // Bug 606 test case, should crash if bug is not fixed
60
    // Bug 606 test case, should crash if bug is not fixed
 Lines 107-113    Link Here 
107
  Simulator::Run ();
106
  Simulator::Run ();
108
  Simulator::Destroy ();
107
  Simulator::Destroy ();
109
108
110
  if (!WRITE_VECTORS) CheckResults ();
109
  CheckResults ();
111
110
112
  delete m_nodes, m_nodes = 0;
111
  delete m_nodes, m_nodes = 0;
113
}
112
}
 Lines 161-168    Link Here 
161
  p.Stop (m_time);
160
  p.Stop (m_time);
162
161
163
  // 4. write PCAP
162
  // 4. write PCAP
164
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : GetTempDir ()) + m_prefix;
163
  wifiPhy.EnablePcapAll (CreateTempDirFilename (m_prefix));
165
  wifiPhy.EnablePcapAll (prefix);
166
}
164
}
167
165
168
void
166
void
 Lines 170-184    Link Here 
170
{
168
{
171
  for (uint32_t i = 0; i < m_size; ++i)
169
  for (uint32_t i = 0; i < m_size; ++i)
172
    {
170
    {
173
      std::ostringstream os1, os2;
171
      NS_PCAP_TEST_EXPECT_EQ (m_prefix << "-" << i << "-0.pcap");
174
      // File naming conventions are hard-coded here.
175
      os1 << NS_TEST_SOURCEDIR << m_prefix << "-" << i << "-0.pcap";
176
      os2 << GetTempDir () << m_prefix << "-" << i << "-0.pcap";
177
178
      uint32_t sec (0), usec (0);
179
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec);
180
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
181
                                                         << " differ starting from " << sec << " s " << usec << " us");
182
    }
172
    }
183
}
173
}
184
174
(-)a/src/aodv/test/bug-772.cc (-17 / +6 lines)
 Lines 43-53    Link Here 
43
#include "ns3/inet-socket-address.h"
43
#include "ns3/inet-socket-address.h"
44
#include "ns3/data-rate.h"
44
#include "ns3/data-rate.h"
45
#include "ns3/packet-sink-helper.h"
45
#include "ns3/packet-sink-helper.h"
46
#include "ns3/pcap-test.h"
46
#include <sstream>
47
#include <sstream>
47
48
48
/// Set to true to rewrite reference traces, leave false to run regression tests
49
const bool WRITE_VECTORS = false;
50
51
namespace ns3 {
49
namespace ns3 {
52
namespace aodv {
50
namespace aodv {
53
51
 Lines 55-61    Link Here 
55
// UdpChainTest
53
// UdpChainTest
56
//-----------------------------------------------------------------------------
54
//-----------------------------------------------------------------------------
57
Bug772ChainTest::Bug772ChainTest (const char * const prefix, const char * const proto, Time t, uint32_t size) : 
55
Bug772ChainTest::Bug772ChainTest (const char * const prefix, const char * const proto, Time t, uint32_t size) : 
58
  TestCase ("Bug 772 UDP/TCP chain regression test"),
56
  TestCase ("Bug 772 UDP and TCP chain regression test"),
59
  m_nodes (0),
57
  m_nodes (0),
60
  m_prefix (prefix),
58
  m_prefix (prefix),
61
  m_proto (proto),
59
  m_proto (proto),
 Lines 82-88    Link Here 
82
  Simulator::Run ();
80
  Simulator::Run ();
83
  Simulator::Destroy ();
81
  Simulator::Destroy ();
84
82
85
  if (!WRITE_VECTORS) CheckResults ();
83
  CheckResults ();
86
84
87
  delete m_nodes, m_nodes = 0;
85
  delete m_nodes, m_nodes = 0;
88
}
86
}
 Lines 143-151    Link Here 
143
  app.Start (Seconds (0.0));
141
  app.Start (Seconds (0.0));
144
142
145
  // 4. write PCAP on the first and last nodes only
143
  // 4. write PCAP on the first and last nodes only
146
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : GetTempDir ()) + m_prefix;
144
  wifiPhy.EnablePcap (CreateTempDirFilename (m_prefix), devices.Get (0));
147
  wifiPhy.EnablePcap (prefix, devices.Get (0));
145
  wifiPhy.EnablePcap (CreateTempDirFilename (m_prefix), devices.Get (m_size-1));
148
  wifiPhy.EnablePcap (prefix, devices.Get (m_size-1));
149
}
146
}
150
147
151
void
148
void
 Lines 153-167    Link Here 
153
{
150
{
154
  for (uint32_t i = 0; i < m_size; i += (m_size - 1) /*first and last nodes only*/)
151
  for (uint32_t i = 0; i < m_size; i += (m_size - 1) /*first and last nodes only*/)
155
    {
152
    {
156
      std::ostringstream os1, os2;
153
      NS_PCAP_TEST_EXPECT_EQ(m_prefix << "-" << i << "-0.pcap");
157
      // File naming conventions are hard-coded here.
158
      os1 << NS_TEST_SOURCEDIR << m_prefix << "-" << i << "-0.pcap";
159
      os2 << GetTempDir () << m_prefix << "-" << i << "-0.pcap";
160
161
      uint32_t sec (0), usec (0);
162
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec);
163
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
164
                                                         << " differ starting from " << sec << " s " << usec << " us");
165
    }
154
    }
166
}
155
}
167
156
(-)a/src/aodv/wscript (-2 / +2 lines)
 Lines 14-27    Link Here 
14
	'helper/aodv-helper.cc',
14
	'helper/aodv-helper.cc',
15
        ]
15
        ]
16
16
17
    aodv_test = bld.create_ns3_module_test_library('aodv')
17
    aodv_test_source = [
18
    aodv_test.source = [
19
        'test/aodv-id-cache-test-suite.cc',
18
        'test/aodv-id-cache-test-suite.cc',
20
        'test/aodv-test-suite.cc',
19
        'test/aodv-test-suite.cc',
21
        'test/aodv-regression.cc',
20
        'test/aodv-regression.cc',
22
        'test/bug-772.cc',
21
        'test/bug-772.cc',
23
        'test/loopback.cc',
22
        'test/loopback.cc',
24
        ]
23
        ]
24
    aodv_test = bld.create_ns3_module_test_library('aodv', aodv_test_source)
25
25
26
    headers = bld.new_task_gen('ns3header')
26
    headers = bld.new_task_gen('ns3header')
27
    headers.module = 'aodv'
27
    headers.module = 'aodv'
(-)a/src/applications/wscript (-2 / +3 lines)
 Lines 27-36    Link Here 
27
        'helper/v4ping-helper.cc',
27
        'helper/v4ping-helper.cc',
28
        ]
28
        ]
29
29
30
    applications_test = bld.create_ns3_module_test_library('applications')
30
    applications_test_source = [
31
    applications_test.source = [
32
        'test/udp-client-server-test.cc',
31
        'test/udp-client-server-test.cc',
33
        ]
32
        ]
33
    applications_test = bld.create_ns3_module_test_library('applications',
34
                                                           applications_test_source)
34
35
35
    headers = bld.new_task_gen('ns3header')
36
    headers = bld.new_task_gen('ns3header')
36
    headers.module = 'applications'
37
    headers.module = 'applications'
(-)a/src/click/wscript (-2 / +3 lines)
 Lines 92-101    Link Here 
92
        'helper/click-internet-stack-helper.cc',
92
        'helper/click-internet-stack-helper.cc',
93
        ]
93
        ]
94
94
95
    module_test = bld.create_ns3_module_test_library('click')
95
    module_test_source = [
96
    module_test.source = [
97
        'test/ipv4-click-routing-test.cc',
96
        'test/ipv4-click-routing-test.cc',
98
        ]
97
        ]
98
    module_test = bld.create_ns3_module_test_library('click',
99
                                                     module_test_source)
99
100
100
    if bld.env['NSCLICK'] and bld.env['DL']:
101
    if bld.env['NSCLICK'] and bld.env['DL']:
101
        module.uselib      = 'NSCLICK DL'
102
        module.uselib      = 'NSCLICK DL'
(-)3c68eb316f5f (+270 lines)
Added Link Here 
1
#include "system-path.h"
2
#include "fatal-error.h"
3
#include "assert.h"
4
#include "ns3/core-config.h"
5
#include <stdlib.h>
6
#include <errno.h>
7
#include <string.h>
8
#if defined (HAVE_DIRENT_H) and defined (HAVE_SYS_TYPES_H)
9
#define HAVE_OPENDIR
10
#include <sys/types.h>
11
#include <dirent.h>
12
#endif
13
#if defined (HAVE_SYS_STAT_H) and defined (HAVE_SYS_TYPES_H)
14
#define HAVE_MKDIR_H
15
#include <sys/types.h>
16
#include <sys/stat.h>
17
#endif
18
#include <sstream>
19
#ifdef __APPLE__
20
#include <mach-o/dyld.h>
21
#endif /* __APPLE__ */
22
23
24
#if defined (__win32__)
25
#define SYSTEM_PATH_SEP "\\"
26
#else
27
#define SYSTEM_PATH_SEP "/"
28
#endif
29
30
namespace ns3 {
31
32
namespace SystemPath {
33
34
std::string Dirname (std::string path)
35
{
36
  std::list<std::string> elements = Split (path);
37
  std::list<std::string>::const_iterator last = elements.end();
38
  last--;
39
  return Join (elements.begin (), last);
40
}
41
42
std::string FindSelfDirectory (void)
43
{
44
  /** 
45
   * This function returns the path to the running $PREFIX.
46
   * Mac OS X: _NSGetExecutablePath() (man 3 dyld)
47
   * Linux: readlink /proc/self/exe
48
   * Solaris: getexecname()
49
   * FreeBSD: sysctl CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1
50
   * BSD with procfs: readlink /proc/curproc/file
51
   * Windows: GetModuleFileName() with hModule = NULL
52
   */
53
  std::string filename;
54
#if defined(__linux__)
55
  {
56
    ssize_t size = 1024;
57
    char *buffer = (char*)malloc (size);
58
    memset (buffer, 0, size);
59
    int status;
60
    while (true)
61
      {
62
        status = readlink("/proc/self/exe", buffer, size);
63
        if (status != 1 || (status == -1 && errno != ENAMETOOLONG))
64
          {
65
            break;
66
          }
67
        size *= 2;
68
        free (buffer);
69
        buffer = (char*)malloc (size);
70
	memset (buffer, 0, size);
71
      }
72
    if (status == -1)
73
      {
74
        NS_FATAL_ERROR ("Oops, could not find self directory.");
75
      }
76
    filename = buffer;
77
    free (buffer);
78
  }
79
#elif defined (__win32__)
80
  {
81
    // XXX: untested. it should work if code is compiled with
82
    // LPTSTR = char *
83
    DWORD size = 1024;
84
    LPTSTR lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size);
85
    DWORD status = GetModuleFilename (0, lpFilename, size);
86
    while (status == size)
87
      {
88
	size = size * 2;
89
	free (lpFilename);
90
	lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size);
91
	status = GetModuleFilename (0, lpFilename, size);
92
      }
93
    NS_ASSERT (status != 0);
94
    filename = lpFilename;
95
    free (lpFilename);
96
  }
97
#elif defined (__APPLE__)
98
  {
99
    uint32_t bufsize = 1024;
100
    char *buffer = (char *) malloc (bufsize);
101
    NS_ASSERT (buffer != 0);
102
    int status = _NSGetExecutablePath (buffer, &bufsize);
103
    if (status == -1)
104
      {
105
	free (buffer);
106
	buffer = (char *) malloc (bufsize);
107
	status = _NSGetExecutablePath (buffer, &bufsize);
108
      }
109
    NS_ASSERT (status == 0);
110
    filename = buffer;
111
    free (buffer);
112
  } 
113
#endif
114
    return Dirname (filename);
115
}
116
  
117
std::string Append (std::string left, std::string right)
118
{
119
  // removing trailing separators from 'left'
120
  while (true)
121
    {
122
      std::string::size_type lastSep = left.rfind (SYSTEM_PATH_SEP);
123
      if (lastSep != left.size () - 1)
124
	{
125
	  break;
126
	}
127
      left = left.substr (0, left.size () - 1);
128
    } 
129
  std::string retval = left + SYSTEM_PATH_SEP + right;
130
  return retval;
131
}
132
133
std::list<std::string> Split (std::string path)
134
{
135
  std::list<std::string> retval;
136
  std::string::size_type current = 0, next = 0;
137
  next = path.find (SYSTEM_PATH_SEP, current);
138
  while (next != std::string::npos)
139
    {
140
      std::string item = path.substr (current, next - current);
141
      retval.push_back (item);
142
      current = next + 1;
143
      next = path.find (SYSTEM_PATH_SEP, current);
144
    }
145
  std::string item = path.substr (current, next - current);
146
  retval.push_back (item);
147
  return retval;
148
}
149
150
std::string Join (std::list<std::string>::const_iterator begin,
151
		  std::list<std::string>::const_iterator end)
152
{
153
  std::string retval = "";
154
  for (std::list<std::string>::const_iterator i = begin; i != end; i++)
155
    {
156
      if (i == begin)
157
	{
158
	  retval = *i;
159
	}
160
      else
161
	{
162
	  retval = retval + SYSTEM_PATH_SEP + *i;
163
	}
164
    }
165
  return retval;
166
}
167
  
168
std::list<std::string> ReadFiles (std::string path)
169
{
170
  std::list<std::string> files;
171
#if defined HAVE_OPENDIR
172
  DIR *dp = opendir (path.c_str ());
173
  if (dp == NULL)
174
    {
175
      NS_FATAL_ERROR ("Could not open directory=" << path);
176
    }
177
  struct dirent *de = readdir (dp);
178
  while (de != 0)
179
    {
180
      files.push_back (de->d_name);
181
      de = readdir (dp);
182
    }
183
  closedir (dp);
184
#elif defined (HAVE_FIND_FIRST_FILE)
185
  // XXX: untested
186
  HANDLE hFind;
187
  WIN32_FIND_DATA fileData;
188
  
189
  hFind = FindFirstFile (path.c_str (), &FindFileData);
190
  if (hFind == INVALID_HANDLE_VALUE)
191
    {
192
      NS_FATAL_ERROR ("Could not open directory=" << path);
193
    }
194
  do
195
    {
196
      files.push_back (fileData.cFileName);
197
    } while (FindNextFile (hFind, &fileData));
198
  FindClose(hFind);
199
#else
200
#error "No support for reading a directory on this platform"
201
#endif
202
  return files;
203
}
204
205
std::string 
206
MakeTemporaryDirectoryName (void)
207
{
208
  char *path = NULL;
209
210
  path = getenv ("TMP");
211
  if (path == NULL)
212
    {
213
      path = getenv ("TEMP");
214
      if (path == NULL)
215
	{
216
	  path = const_cast<char *> ("/tmp");
217
	}
218
    }
219
220
  //
221
  // Just in case the user wants to go back and find the output, we give
222
  // a hint as to which dir we created by including a time hint.
223
  //
224
  time_t now = time (NULL);
225
  struct tm *tm_now = localtime (&now);
226
  //
227
  // But we also randomize the name in case there are multiple users doing
228
  // this at the same time
229
  //
230
  srand (time (0));
231
  long int n = rand ();
232
233
  //
234
  // The final path to the directory is going to look something like
235
  // 
236
  //   /tmp/ns3-14.30.29.32767
237
  //
238
  // The first segment comes from one of the temporary directory env 
239
  // variables or /tmp if not found.  The directory name starts with an
240
  // identifier telling folks who is making all of the temp directories
241
  // and then the local time (in this case 14.30.29 -- which is 2:30 and
242
  // 29 seconds PM).
243
  //
244
  std::ostringstream oss;
245
  oss << path << SYSTEM_PATH_SEP << "ns-3." << tm_now->tm_hour << "."
246
      << tm_now->tm_min << "." << tm_now->tm_sec << "." << n;
247
248
  return oss.str ();
249
}
250
251
void 
252
MakeDirectories (std::string path)
253
{
254
  std::list<std::string> elements = Split (path);
255
  for (std::list<std::string>::const_iterator i = elements.begin (); i != elements.end (); ++i)
256
    {
257
      std::string tmp = Join (elements.begin (), i);
258
#if defined(HAVE_MKDIR_H)
259
      mkdir (tmp.c_str (), S_IRWXU);
260
#endif
261
    }
262
#if defined(HAVE_MKDIR_H)
263
  mkdir (path.c_str (), S_IRWXU);
264
#endif
265
266
}
267
268
} // namespace SystemPath
269
270
} // namespace ns3
(-)3c68eb316f5f (+72 lines)
Added Link Here 
1
#ifndef SYSTEM_PATH
2
#define SYSTEM_PATH
3
4
#include <string>
5
#include <list>
6
7
namespace ns3 {
8
9
/**
10
 * \brief Encapsulate OS-specific functions to manipulate file and directory paths.
11
 *
12
 * The functions provided here are used mostly to implement the ns-3 test framework.
13
 */
14
namespace SystemPath {
15
16
  /**
17
   * \return the directory in which the currently-executing binary is located
18
   */
19
  std::string FindSelfDirectory (void);
20
  
21
  /**
22
   * \param left a path element
23
   * \param right a path element
24
   * \return a concatenation of the two input paths
25
   */
26
  std::string Append (std::string left, std::string right);
27
28
  /**
29
   * \param path a path
30
   * \return a list of path elements that can be joined together again with
31
   *         the Join function.
32
   * \sa ns3::SystemPath::Join
33
   */
34
  std::list<std::string> Split (std::string path);
35
36
  /**
37
   * \param begin iterator to first element to join
38
   * \param end iterator to last element to join
39
   * \return a path that is a concatenation of all the input elements.
40
   */
41
  std::string Join (std::list<std::string>::const_iterator begin,
42
		    std::list<std::string>::const_iterator end);
43
  
44
  /**
45
   * \param path a path which identifies a directory
46
   * \return a list of the filenames which are located in the input directory
47
   */
48
  std::list<std::string> ReadFiles (std::string path);
49
50
  /**
51
   * \return a path which identifies a temporary directory.
52
   *
53
   * The returned path identifies a directory which does not exist yet
54
   * Call ns3::SystemPath::MakeDirectories to create it. Yes, there is a
55
   * well-known security race in this API but we don't care in ns-3.
56
   */
57
  std::string MakeTemporaryDirectoryName (void);
58
59
  /**
60
   * \param path a path to a directory
61
   *
62
   * Create all the directories leading to path.
63
   */
64
  void MakeDirectories (std::string path);
65
66
} // namespace SystemPath
67
68
69
} // namespace ns3
70
71
72
#endif /* SYSTEM_PATH */
(-)a/src/core/model/test.cc (-636 / +667 lines)
 Lines 19-61    Link Here 
19
#include "test.h"
19
#include "test.h"
20
#include "assert.h"
20
#include "assert.h"
21
#include "abort.h"
21
#include "abort.h"
22
#include "system-path.h"
22
#include <math.h>
23
#include <math.h>
24
#include <string.h>
25
#include <vector>
26
#include <list>
23
27
24
// Set to true to enable a segmentation fault upon a test case macro test 
25
// failing (for debugging purposes)
26
bool gBreakOnFailure = false;
27
28
28
namespace ns3 {
29
namespace ns3 {
29
30
30
//
31
// XML files have restrictions on certain characters that may be present in
32
// data.  We need to replace these characters with their alternate 
33
// representation on the way into the XML file.
34
//
35
std::string
36
ReplaceXmlSpecialCharacters (std::string xml)
37
{
38
  std::string specials = "<>&\"'";
39
  std::string replacements[] = { "&lt;", "&gt;", "&amp;", "&#39;", "&quot;"};
40
  std::string result;
41
  std::size_t index, length = xml.length ();
42
43
  for (size_t i = 0; i < length; ++i)
44
    {
45
      char character = xml[i];
46
47
      if ((index = specials.find (character)) == std::string::npos)
48
        {
49
          result.push_back (character);
50
        }
51
      else
52
        {
53
          result += replacements[index];
54
        }
55
    }
56
  return result;
57
}
58
59
bool
31
bool
60
TestDoubleIsEqual (const double x1, const double x2, const double epsilon)
32
TestDoubleIsEqual (const double x1, const double x2, const double epsilon)
61
{
33
{
 Lines 83-722    Link Here 
83
  return true;
55
  return true;
84
} 
56
} 
85
57
58
struct TestCaseFailure
59
{
60
  TestCaseFailure (std::string _cond, std::string _actual, 
61
                   std::string _limit, std::string _message, 
62
                   std::string _file, int32_t _line);
63
  std::string cond;
64
  std::string actual;
65
  std::string limit;
66
  std::string message; 
67
  std::string file;
68
  int32_t line;
69
};
70
struct TestCase::Result
71
{
72
  Result ();
73
  SystemWallClockMs clock;
74
  std::vector<TestCaseFailure> failure;
75
  bool childrenFailed;
76
};
77
78
class TestRunnerImpl
79
{
80
public:
81
  void AddTestSuite (TestSuite *testSuite);
82
  void StartTestCase (std::string name);
83
  void EndTestCase (void);
84
  void ReportTestFailure (std::string cond, std::string actual, 
85
                      std::string limit, std::string message, 
86
                      std::string file, int32_t line);
87
  bool MustAssertOnFailure (void) const;
88
  bool MustContinueOnFailure (void) const;
89
  bool MustUpdateData (void) const;
90
  std::string GetTopLevelSourceDir (void) const;
91
  std::string GetTempDir (void) const;
92
93
  int Run (int argc, char *argv[]);
94
95
  static TestRunnerImpl *Instance (void);
96
97
private:
98
  TestRunnerImpl ();
99
  ~TestRunnerImpl ();
100
101
  bool IsTopLevelSourceDir (std::string path) const;
102
  std::string ReplaceXmlSpecialCharacters (std::string xml) const;
103
  void PrintReport (TestCase *test, std::ostream *os, bool xml, int level);
104
  void PrintTestNameList (std::list<TestCase *>::const_iterator begin, 
105
                          std::list<TestCase *>::const_iterator end) const;
106
  void PrintTestTypeList (void) const;
107
  void PrintHelp (const char *programName) const;
108
  std::list<TestCase *> FilterTests (std::string testName, enum TestSuite::Type testType) const;
109
110
111
  typedef std::vector<TestSuite *> TestSuiteVector;
112
113
  TestSuiteVector m_suites;
114
  std::string m_tempDir;
115
  bool m_verbose;
116
  bool m_assertOnFailure;
117
  bool m_continueOnFailure;
118
  bool m_updateData;
119
};
120
121
122
123
TestCaseFailure::TestCaseFailure (std::string _cond, std::string _actual, 
124
                                  std::string _limit, std::string _message, 
125
                                  std::string _file, int32_t _line)
126
  : cond (_cond), actual (_actual), limit (_limit),
127
    message (_message), file (_file), line (_line)
128
{}
129
TestCase::Result::Result ()
130
  : childrenFailed (false)
131
{}
132
133
86
134
87
TestCase::TestCase (std::string name)
135
TestCase::TestCase (std::string name)
88
  : m_name (name), 
136
  : m_parent (0),
89
    m_verbose (false), 
137
    m_dataDir (""),
90
    m_continueOnFailure (false), 
138
    m_runner (0),
91
    m_detailsReported (false), 
139
    m_result (0),
92
    m_basedir ("invalid"), 
140
    m_name (name)
93
    m_tempdir ("invalid"), 
94
    m_ofs (0), 
95
    m_error (false)
96
{
141
{
97
}
142
}
98
143
99
TestCase::~TestCase ()
144
TestCase::~TestCase ()
100
{
145
{
146
  NS_ASSERT (m_runner == 0);
147
  m_parent = 0;
148
  delete m_result;
149
  for (std::vector<TestCase *>::const_iterator i = m_children.begin (); i != m_children.end (); ++i)
150
    {
151
      delete *i;
152
    }
153
  m_children.clear ();
101
}
154
}
102
155
103
void
156
void
104
TestCase::ReportStart  (void)
157
TestCase::AddTestCase (TestCase *testCase)
105
{
158
{
106
  DoReportStart ();
159
  m_children.push_back (testCase);
160
  testCase->m_parent = this;
161
162
  std::string::size_type slash, antislash;
163
  slash = testCase->m_name.find ("/");
164
  antislash = testCase->m_name.find ("\\");
165
  if (slash != std::string::npos || antislash != std::string::npos)
166
    {
167
      std::string fullname = testCase->m_name;
168
      TestCase *current = testCase->m_parent;
169
      while (current != 0)
170
        {
171
          fullname = current->m_name + "/" + fullname;
172
          current = current->m_parent;
173
        }
174
      if (slash != std::string::npos)
175
        {
176
          NS_FATAL_ERROR ("Invalid test name: cannot contain slashes: \"" << fullname << "\"");
177
        }
178
      if (antislash != std::string::npos)
179
        {
180
          NS_FATAL_ERROR ("Invalid test name: cannot contain antislashes: \"" << fullname << "\"");
181
        }
182
    }
107
}
183
}
108
184
109
void
185
bool
110
TestCase::ReportCaseSuccess  (void)
186
TestCase::IsFailed (void) const
111
{
187
{
112
  UpdateErrorStatus (false);
188
  return m_result->childrenFailed || !m_result->failure.empty ();
113
  DoReportCaseSuccess ();
114
}
189
}
115
190
191
void 
192
TestCase::Run (TestRunnerImpl *runner)
193
{
194
  m_result = new Result ();
195
  m_runner = runner;
196
  DoSetup ();
197
  m_result->clock.Start ();
198
  for (std::vector<TestCase *>::const_iterator i = m_children.begin (); i != m_children.end (); ++i)
199
    {
200
      TestCase *test = *i;
201
      test->Run (runner);
202
      if (IsFailed ())
203
        {
204
          goto out;
205
        }
206
    }
207
  DoRun ();
208
 out:
209
  m_result->clock.End ();
210
  DoTeardown ();
211
  m_runner = 0;
212
}
213
std::string 
214
TestCase::GetName (void) const
215
{
216
  return m_name;
217
}
116
void
218
void
117
TestCase::ReportCaseFailure  (void)
219
TestCase::ReportTestFailure (std::string cond, std::string actual, 
220
                             std::string limit, std::string message, 
221
                             std::string file, int32_t line)
118
{
222
{
119
  UpdateErrorStatus (true);
223
  m_result->failure.push_back (TestCaseFailure (cond, actual, limit,
120
  DoReportCaseFailure ();
224
                                                message, file, line));
225
  // set childrenFailed flag on parents.
226
  struct TestCase *current = m_parent;
227
  while (current != 0)
228
    {
229
      current->m_result->childrenFailed = true;
230
      current = current->m_parent;
231
    }
232
233
}
234
bool 
235
TestCase::MustAssertOnFailure (void) const
236
{
237
  return m_runner->MustAssertOnFailure ();
238
}
239
bool 
240
TestCase::MustContinueOnFailure (void) const
241
{
242
  return m_runner->MustContinueOnFailure ();
121
}
243
}
122
244
123
void
245
std::string 
124
TestCase::ReportTestFailure  (
246
TestCase::CreateDataDirFilename (std::string filename)
125
  std::string cond, 
126
  std::string actual, 
127
  std::string limit, 
128
  std::string message, 
129
  std::string file, 
130
  int32_t line)
131
{
247
{
132
  UpdateErrorStatus (true);
248
  const TestCase *current = this;
133
  DoReportTestFailure (cond, actual, limit, message, file, line);
249
  while (current->m_dataDir == "" && current != 0)
134
  m_detailsReported = true; 
250
    {
251
      current = current->m_parent;
252
    }
253
  if (current == 0)
254
    {
255
      NS_FATAL_ERROR ("No one called SetDataDir prior to calling this function");
256
    }
257
258
  std::string a = SystemPath::Append (m_runner->GetTopLevelSourceDir (), current->m_dataDir);
259
  std::string b = SystemPath::Append (a, filename);
260
  return b;
135
}
261
}
136
262
std::string 
137
void
263
TestCase::CreateTempDirFilename (std::string filename)
138
TestCase::ReportEnd  (void)
139
{
264
{
140
  DoReportStart ();
265
  if (m_runner->MustUpdateData ())
141
}
142
143
void
144
TestCase::Run (void)
145
{
146
  //
147
  // We set up a flag to make sure the user plays by the rules and actually
148
  // does something to report the details of an error.
149
  //
150
  m_detailsReported = false; 
151
152
  DoReportStart ();
153
  DoSetup ();
154
155
  DoRun ();
156
157
  DoTeardown ();
158
159
  if (GetErrorStatus () == false)
160
    {
266
    {
161
      DoReportCaseSuccess ();
267
      return CreateDataDirFilename (filename);
162
    }
268
    }
163
  else
269
  else
164
    {
270
    {
165
      //
271
      std::list<std::string> names;
166
      // It is a programming error to return an error from a test case without 
272
      const TestCase *current = this;
167
      // calling ReportTestFailure.  Typically this is done automagically when
273
      while (current != 0)
168
      // using the ASSERT or EXPECT macros.  If you don't use these, you must
274
        {
169
      // ReportTestFailure on any errors yourself, which will set 
275
          names.push_front (current->m_name);
170
      // m_detailsReported and make us happy.
276
          current = current->m_parent;
171
      //
277
        }
172
      NS_ASSERT_MSG (m_detailsReported, "The details of a failing test was not reported");
278
      std::string tempDir = SystemPath::Append (m_runner->GetTempDir (), SystemPath::Join (names.begin (), names.end ()));
173
279
      SystemPath::MakeDirectories (tempDir);
174
      DoReportCaseFailure ();
280
      return SystemPath::Append (tempDir, filename);
175
    }
281
    }
176
282
}
177
  DoReportEnd ();
283
bool 
178
284
TestCase::GetErrorStatus (void) const
179
  return;
285
{
286
  return IsStatusFailure ();
287
}
288
bool 
289
TestCase::IsStatusFailure (void) const
290
{
291
  return !IsStatusSuccess ();
292
}
293
bool 
294
TestCase::IsStatusSuccess (void) const
295
{
296
  return m_result->failure.empty ();
180
}
297
}
181
298
182
void 
299
void 
183
TestCase::SetVerbose (bool verbose)
300
TestCase::SetDataDir (std::string directory)
184
{
301
{
185
  m_verbose = verbose;
302
  m_dataDir = directory;
186
}
187
188
void 
189
TestCase::SetContinueOnFailure (bool continueOnFailure)
190
{
191
  m_continueOnFailure = continueOnFailure;
192
}
193
194
void 
195
TestCase::SetName (std::string name)
196
{
197
  m_name = name;
198
}
199
200
std::string 
201
TestCase::GetName (void)
202
{
203
  return m_name;
204
}
205
206
void 
207
TestCase::SetBaseDir (std::string basedir)
208
{
209
  //
210
  // C and C++ allow one to use forward slashes even on systems where the 
211
  // separator is actually a backslash.
212
  //
213
  if (basedir[basedir.length () - 1] != '/')
214
    {
215
      m_basedir = basedir + "/";
216
    }
217
  else
218
    {
219
      m_basedir = basedir;
220
    }
221
}
222
223
std::string 
224
TestCase::GetBaseDir (void)
225
{
226
  return m_basedir;
227
}
228
229
void 
230
TestCase::SetTempDir (std::string tempdir)
231
{
232
  //
233
  // C and C++ allow one to use forward slashes even on systems where the 
234
  // separator is actually a backslash.
235
  //
236
  if (tempdir[tempdir.length () - 1] != '/')
237
    {
238
      m_tempdir = tempdir + "/";
239
    }
240
  else
241
    {
242
      m_tempdir = tempdir;
243
    }
244
}
245
246
std::string 
247
TestCase::GetTempDir (void)
248
{
249
  return m_tempdir;
250
}
251
252
std::string 
253
TestCase::GetSourceDir (std::string file)
254
{
255
  //
256
  // The <file> parameter is actually going to be __FILE__ which may have 
257
  // backslashes in it on win32 systems.  For example,
258
  //
259
  //   ..\src\common\pcap-file-test-suite.cc  (win32)
260
  //
261
  // or
262
  //
263
  //   ../src/common/pcap-file-test-suite.cc  (grown-up systems)
264
  //
265
#ifdef WIN32
266
  std::string::size_type relPathBegin = file.find_first_of ("\\");
267
  std::string::size_type relPathEnd = file.find_last_of ("\\");
268
#else
269
  std::string::size_type relPathBegin = file.find_first_of ("/");
270
  std::string::size_type relPathEnd = file.find_last_of ("/");
271
#endif
272
273
  NS_ABORT_MSG_IF (relPathBegin == std::string::npos, "TestCase::GetSourceDir(): Internal Error");
274
  NS_ABORT_MSG_IF (relPathEnd == std::string::npos, "TestCase::GetSourceDir(): Internal Error");
275
276
  return GetBaseDir () + file.substr (relPathBegin, relPathEnd + 1 - relPathBegin);
277
}
278
279
void 
280
TestCase::SetStream (std::ofstream *ofs)
281
{
282
  m_ofs = ofs;
283
}
284
285
std::ofstream *
286
TestCase::GetStream (void)
287
{
288
  return m_ofs;
289
}
290
291
void 
292
TestCase::UpdateErrorStatus (bool error)
293
{
294
  m_error |= error;
295
}
296
297
void 
298
TestCase::SetErrorStatus (bool error)
299
{
300
  m_error = error;
301
}
302
303
bool
304
TestCase::GetErrorStatus (void)
305
{
306
  return m_error;
307
}
308
309
bool
310
TestCase::ContinueOnFailure (void)
311
{
312
  return m_continueOnFailure;
313
}
314
315
void
316
TestCase::DoReportStart  (void)
317
{
318
  m_msClock.Start ();
319
320
  if (m_ofs == 0)
321
    {
322
      return;
323
    }
324
  *m_ofs << "  <TestCase>" << std::endl;
325
  *m_ofs << "    <CaseName>" << ReplaceXmlSpecialCharacters (GetName ()) << "</CaseName>" << std::endl;
326
}
327
328
void
329
TestCase::DoReportCaseSuccess  (void)
330
{
331
  if (m_ofs == 0)
332
    {
333
      return;
334
    }
335
  *m_ofs << "    <CaseResult>PASS</CaseResult>" << std::endl;
336
}
337
338
void
339
TestCase::DoReportCaseFailure  (void)
340
{
341
  if (m_ofs == 0)
342
    {
343
      return;
344
    }
345
  *m_ofs << "    <CaseResult>FAIL</CaseResult>" << std::endl;
346
}
347
348
void
349
TestCase::DoReportTestFailure  (
350
  std::string cond, 
351
  std::string actual, 
352
  std::string limit, 
353
  std::string message, 
354
  std::string file, 
355
  int32_t line)
356
{
357
  if (m_ofs == 0)
358
    {
359
      return;
360
    }
361
362
  *m_ofs << "    <FailureDetails>" << std::endl;
363
  *m_ofs << "      <Condition>" << ReplaceXmlSpecialCharacters (cond) << "</Condition>" << std::endl;
364
  *m_ofs << "      <Actual>" << ReplaceXmlSpecialCharacters (actual) << "</Actual>" << std::endl;
365
  *m_ofs << "      <Limit>" << ReplaceXmlSpecialCharacters (limit) << "</Limit>" << std::endl;
366
  *m_ofs << "      <Message>" << ReplaceXmlSpecialCharacters (message) << "</Message>" << std::endl;
367
  *m_ofs << "      <File>" << ReplaceXmlSpecialCharacters (file) << "</File>" << std::endl;
368
  *m_ofs << "      <Line>" << line << "</Line>" << std::endl;
369
  *m_ofs << "    </FailureDetails>" << std::endl;
370
}
371
372
void
373
TestCase::DoReportEnd  (void)
374
{
375
  m_msClock.End ();
376
377
  if (m_ofs == 0)
378
    {
379
      return;
380
    }
381
382
  (*m_ofs).precision (3);
383
  *m_ofs << std::fixed;
384
385
  const double MS_PER_SEC = 1000.;
386
387
  *m_ofs << "    <CaseTime>" << "real " << m_msClock.GetElapsedReal () / MS_PER_SEC
388
         << " user " << m_msClock.GetElapsedUser () / MS_PER_SEC
389
         << " system " << m_msClock.GetElapsedSystem () / MS_PER_SEC
390
         << "</CaseTime>" << std::endl;
391
392
  *m_ofs << "  </TestCase>" << std::endl;
393
}
303
}
394
304
395
void 
305
void 
396
TestCase::DoSetup (void)
306
TestCase::DoSetup (void)
307
{}
308
void 
309
TestCase::DoTeardown (void)
310
{}
311
312
313
TestSuite::TestSuite (std::string name, TestSuite::Type type)
314
  : TestCase (name), 
315
    m_type (type)
397
{
316
{
317
  TestRunnerImpl::Instance ()->AddTestSuite (this);
398
}
318
}
399
319
400
void 
320
TestSuite::Type 
401
TestCase::DoTeardown (void)
402
{
403
}
404
405
TestSuite::TestSuite (std::string name, TestType type)
406
  : m_name (name), 
407
    m_verbose (false), 
408
    m_basedir ("invalid"), 
409
    m_tempdir ("invalid"), 
410
    m_ofs (0), 
411
    m_error (false), 
412
    m_type (type)
413
{
414
  TestRunner::AddTestSuite (this);
415
}
416
417
TestSuite::~TestSuite ()
418
{
419
  for (TestCaseVector_t::iterator i = m_tests.begin (); i != m_tests.end (); ++i)
420
    {
421
      delete *i;
422
      *i = 0;
423
    }
424
425
  m_tests.erase (m_tests.begin (), m_tests.end ());
426
}
427
428
void
429
TestSuite::ReportStart (void)
430
{
431
  DoReportStart ();
432
}
433
434
void
435
TestSuite::ReportSuccess (void)
436
{
437
  UpdateErrorStatus (false);
438
  DoReportSuccess ();
439
}
440
441
void
442
TestSuite::ReportFailure (void)
443
{
444
  UpdateErrorStatus (true);
445
  DoReportFailure ();
446
}
447
448
void
449
TestSuite::ReportEnd (void)
450
{
451
  DoReportEnd ();
452
}
453
454
bool
455
TestSuite::Run (void)
456
{
457
  DoReportStart ();
458
459
  DoSetup (); 
460
  DoRun ();
461
  DoTeardown ();
462
463
  if (GetErrorStatus () == false)
464
    {
465
      DoReportSuccess ();
466
    }
467
  else
468
    {
469
      DoReportFailure ();
470
    }
471
472
  DoReportEnd ();
473
474
  return GetErrorStatus ();
475
}
476
477
uint32_t
478
TestSuite::AddTestCase (TestCase *testCase)
479
{
480
  uint32_t index = m_tests.size ();
481
  m_tests.push_back (testCase);
482
  return index;
483
}
484
485
uint32_t 
486
TestSuite::GetNTestCases (void)
487
{
488
  return m_tests.size ();
489
}
490
491
TestCase *
492
TestSuite::GetTestCase (uint32_t n)
493
{
494
  return m_tests[n];
495
}
496
497
TestSuite::TestType 
498
TestSuite::GetTestType (void)
321
TestSuite::GetTestType (void)
499
{
322
{
500
  return m_type;
323
  return m_type;
501
}
324
}
502
325
503
void 
326
void 
504
TestSuite::SetVerbose (bool verbose)
505
{
506
  m_verbose = verbose;
507
}
508
509
void 
510
TestSuite::SetContinueOnFailure (bool continueOnFailure)
511
{
512
  m_continueOnFailure = continueOnFailure;
513
}
514
515
void 
516
TestSuite::SetName (std::string name)
517
{
518
  m_name = name;
519
}
520
521
std::string 
522
TestSuite::GetName (void)
523
{
524
  return m_name;
525
}
526
527
void 
528
TestSuite::SetBaseDir (std::string basedir)
529
{
530
  //
531
  // C and C++ allow one to use forward slashes even on systems where the 
532
  // separator is actually a backslash.
533
  //
534
  if (basedir[basedir.length () - 1] != '/')
535
    {
536
      m_basedir = basedir + "/";
537
    }
538
  else
539
    {
540
      m_basedir = basedir;
541
    }
542
}
543
544
std::string 
545
TestSuite::GetBaseDir (void)
546
{
547
  return m_basedir;
548
}
549
550
void 
551
TestSuite::SetTempDir (std::string tempdir)
552
{
553
  //
554
  // C and C++ allow one to use forward slashes even on systems where the 
555
  // separator is actually a backslash.
556
  //
557
  if (tempdir[tempdir.length () - 1] != '/')
558
    {
559
      m_tempdir = tempdir + "/";
560
    }
561
  else
562
    {
563
      m_tempdir = tempdir;
564
    }
565
}
566
567
std::string 
568
TestSuite::GetTempDir (void)
569
{
570
  return m_tempdir;
571
}
572
573
void 
574
TestSuite::SetStream (std::ofstream *ofs)
575
{
576
  m_ofs = ofs;
577
}
578
579
void 
580
TestSuite::UpdateErrorStatus (bool error)
581
{
582
  m_error |= error;
583
}
584
585
void 
586
TestSuite::SetErrorStatus (bool error)
587
{
588
  m_error = error;
589
}
590
591
bool
592
TestSuite::GetErrorStatus (void)
593
{
594
  return m_error;
595
}
596
597
bool
598
TestSuite::ContinueOnFailure (void)
599
{
600
  return m_continueOnFailure;
601
}
602
603
void
604
TestSuite::DoReportStart (void)
605
{
606
  m_msClock.Start ();
607
608
  if (m_ofs == 0)
609
    {
610
      return;
611
    }
612
  *m_ofs << "<TestSuite>" << std::endl;
613
  *m_ofs << "  <SuiteName>" << ReplaceXmlSpecialCharacters (GetName ()) << "</SuiteName>" << std::endl;
614
}
615
616
void
617
TestSuite::DoReportFailure (void)
618
{
619
  if (m_ofs == 0)
620
    {
621
      return;
622
    }
623
  *m_ofs << "  <SuiteResult>FAIL</SuiteResult>" << std::endl;
624
}
625
626
void
627
TestSuite::DoReportSuccess (void)
628
{
629
  if (m_ofs == 0)
630
    {
631
      return;
632
    }
633
  *m_ofs << "  <SuiteResult>PASS</SuiteResult>" << std::endl;
634
}
635
636
void
637
TestSuite::DoReportEnd (void)
638
{
639
  m_msClock.End ();
640
641
  if (m_ofs == 0)
642
    {
643
      return;
644
    }
645
646
  (*m_ofs).precision (3);
647
  *m_ofs << std::fixed;
648
649
  const double MS_PER_SEC = 1000.;
650
651
  *m_ofs << "  <SuiteTime>" << "real " << m_msClock.GetElapsedReal () / MS_PER_SEC
652
         << " user " << m_msClock.GetElapsedUser () / MS_PER_SEC
653
         << " system " << m_msClock.GetElapsedSystem () / MS_PER_SEC
654
         << "</SuiteTime>" << std::endl;
655
656
  *m_ofs << "</TestSuite>" << std::endl;
657
}
658
659
void 
660
TestSuite::DoSetup (void)
661
{
662
}
663
664
void
665
TestSuite::DoRun (void)
327
TestSuite::DoRun (void)
666
{
328
{}
667
  SetErrorStatus (false);
668
669
  for (TestCaseVector_t::iterator i = m_tests.begin (); i != m_tests.end (); ++i)
670
    {
671
      //
672
      // Set the current options for the test case
673
      //
674
      (*i)->SetVerbose (m_verbose);
675
      (*i)->SetContinueOnFailure (m_continueOnFailure);
676
      (*i)->SetBaseDir (m_basedir);
677
      (*i)->SetTempDir (m_tempdir);
678
      (*i)->SetStream (m_ofs);
679
680
      //
681
      // Run the test case
682
      //
683
      (*i)->Run ();
684
      UpdateErrorStatus ((*i)->GetErrorStatus ());
685
686
      //
687
      // Exit if we have detected an error and we are not allowing multiple failures
688
      //
689
      if (GetErrorStatus () && m_continueOnFailure == false)
690
        {
691
          return;
692
        }
693
    }
694
695
}
696
697
void 
698
TestSuite::DoTeardown (void)
699
{
700
}
701
702
class TestRunnerImpl
703
{
704
public:
705
  uint32_t AddTestSuite (TestSuite *testSuite);
706
  uint32_t GetNTestSuites (void);
707
  TestSuite *GetTestSuite (uint32_t n);
708
  bool RunTestSuite (uint32_t n);
709
710
  static TestRunnerImpl *Instance (void);
711
private:
712
  TestRunnerImpl ();
713
  ~TestRunnerImpl ();
714
715
  typedef std::vector<TestSuite *> TestSuiteVector_t;
716
  TestSuiteVector_t m_suites;
717
};
718
329
719
TestRunnerImpl::TestRunnerImpl ()
330
TestRunnerImpl::TestRunnerImpl ()
331
 : m_tempDir (""),
332
   m_assertOnFailure (false),
333
   m_continueOnFailure (true),
334
   m_updateData (false)
720
{
335
{
721
}
336
}
722
337
 Lines 724-729    Link Here 
724
{
339
{
725
}
340
}
726
341
342
343
727
TestRunnerImpl *
344
TestRunnerImpl *
728
TestRunnerImpl::Instance (void)
345
TestRunnerImpl::Instance (void)
729
{
346
{
 Lines 731-772    Link Here 
731
  return &runner;
348
  return &runner;
732
}
349
}
733
350
734
uint32_t
351
void
735
TestRunnerImpl::AddTestSuite (TestSuite *testSuite)
352
TestRunnerImpl::AddTestSuite (TestSuite *testSuite)
736
{
353
{
737
  uint32_t index = m_suites.size ();
738
  m_suites.push_back (testSuite);
354
  m_suites.push_back (testSuite);
739
  return index;
740
}
355
}
741
356
742
uint32_t 
357
743
TestRunnerImpl::GetNTestSuites (void)
358
bool 
359
TestRunnerImpl::MustAssertOnFailure (void) const
744
{
360
{
745
  return m_suites.size ();
361
  return m_assertOnFailure;
362
}
363
bool 
364
TestRunnerImpl::MustContinueOnFailure (void) const
365
{
366
  return m_continueOnFailure;
746
}
367
}
747
368
748
TestSuite *
369
bool 
749
TestRunnerImpl::GetTestSuite (uint32_t n)
370
TestRunnerImpl::MustUpdateData (void) const
750
{
371
{
751
  return m_suites[n];
372
  return m_updateData;
373
}
374
std::string
375
TestRunnerImpl::GetTempDir (void) const
376
{
377
  return m_tempDir;
378
}
379
bool
380
TestRunnerImpl::IsTopLevelSourceDir (std::string path) const
381
{
382
  bool haveVersion = false;
383
  bool haveLicense = false;
384
  
385
  //
386
  // If there's a file named VERSION and a file named LICENSE in this
387
  // directory, we assume it's our top level source directory.
388
  //
389
390
  std::list<std::string> files = SystemPath::ReadFiles (path);
391
  for (std::list<std::string>::const_iterator i = files.begin (); i != files.end (); ++i)
392
    {
393
      if (*i == "VERSION")
394
        {
395
          haveVersion = true;
396
        }
397
      else if (*i == "LICENSE")
398
        {
399
          haveLicense = true;
400
        }
401
    }
402
  
403
  return haveVersion && haveLicense;
752
}
404
}
753
405
754
uint32_t
406
std::string 
755
TestRunner::AddTestSuite (TestSuite *testSuite)
407
TestRunnerImpl::GetTopLevelSourceDir (void) const
756
{
408
{
757
  return TestRunnerImpl::Instance ()->AddTestSuite (testSuite);
409
  std::string self = SystemPath::FindSelfDirectory ();
410
  std::list<std::string> elements = SystemPath::Split (self);
411
  while (!elements.empty ())
412
    {
413
      std::string path = SystemPath::Join (elements.begin (), elements.end ());
414
      if (IsTopLevelSourceDir (path))
415
        {
416
          return path;
417
        }
418
      elements.pop_back ();
419
    }
420
  NS_FATAL_ERROR ("Could not find source directory from self=" << self);
758
}
421
}
759
422
760
uint32_t
423
//
761
TestRunner::GetNTestSuites (void)
424
// XML files have restrictions on certain characters that may be present in
425
// data.  We need to replace these characters with their alternate 
426
// representation on the way into the XML file.
427
//
428
std::string
429
TestRunnerImpl::ReplaceXmlSpecialCharacters (std::string xml) const
762
{
430
{
763
  return TestRunnerImpl::Instance ()->GetNTestSuites ();
431
  std::string specials = "<>&\"'";
432
  std::string replacements[] = {"&lt;", "&gt;", "&amp;", "&#39;", "&quot;"};
433
  std::string result;
434
  std::size_t index, length = xml.length ();
435
436
  for (size_t i = 0; i < length; ++i)
437
    {
438
      char character = xml[i];
439
440
      if ((index = specials.find (character)) == std::string::npos)
441
        {
442
          result.push_back (character);
443
        }
444
      else
445
        {
446
          result += replacements[index];
447
        }
448
    }
449
  return result;
764
}
450
}
765
451
766
TestSuite *
452
struct Indent
767
TestRunner::GetTestSuite (uint32_t n)
768
{
453
{
769
  return TestRunnerImpl::Instance ()->GetTestSuite (n);
454
  Indent (int level);
455
  int level;
456
};
457
Indent::Indent (int _level)
458
  : level (_level)
459
{}
460
std::ostream &operator << (std::ostream &os, const Indent &val)
461
{
462
  for (int i = 0; i < val.level; i++)
463
    {
464
      os << "  ";
465
    }
466
  return os;
467
}
468
469
void
470
TestRunnerImpl::PrintReport (TestCase *test, std::ostream *os, bool xml, int level)
471
{
472
  if (test->m_result == 0)
473
    {
474
      // Do not print reports for tests that were not run.
475
      return;
476
    }
477
  const double MS_PER_SEC = 1000.;
478
  double real = test->m_result->clock.GetElapsedReal () / MS_PER_SEC;
479
  double user = test->m_result->clock.GetElapsedUser () / MS_PER_SEC;
480
  double system = test->m_result->clock.GetElapsedSystem () / MS_PER_SEC;
481
482
  (*os).precision (3);
483
  *os << std::fixed;
484
485
  std::string statusString = test->IsFailed ()?"FAIL":"PASS";
486
  if (xml)
487
    {
488
      *os << Indent (level) << "<Test>" << std::endl;
489
      *os << Indent (level+1) << "<Name>" << ReplaceXmlSpecialCharacters (test->m_name)
490
          << "</Name>" << std::endl;
491
      *os << Indent (level+1) << "<Result>" << statusString << "</Result>" << std::endl;
492
      *os << Indent (level+1) << "<Time real=\"" << real << "\" user=\"" << user 
493
          << "\" system=\"" << system << "\"/>" << std::endl;
494
      for (uint32_t i = 0; i < test->m_result->failure.size (); i++)
495
        {
496
          TestCaseFailure failure = test->m_result->failure[i];
497
          *os << Indent (level+2) << "<FailureDetails>" << std::endl
498
              << Indent (level+3) << "<Condition>" 
499
              << ReplaceXmlSpecialCharacters (failure.cond) << "</Condition>" << std::endl
500
              << Indent (level+3) << "<Actual>" 
501
              << ReplaceXmlSpecialCharacters (failure.actual) << "</Actual>" << std::endl
502
              << Indent (level+3) << "<Limit>" 
503
              << ReplaceXmlSpecialCharacters (failure.limit) << "</Limit>" << std::endl
504
              << Indent (level+3) << "<Message>" 
505
              << ReplaceXmlSpecialCharacters (failure.message) << "</Message>" << std::endl
506
              << Indent (level+3) << "<File>" 
507
              << ReplaceXmlSpecialCharacters (failure.file) << "</File>" << std::endl
508
              << Indent (level+3) << "<Line>" << failure.line << "</Line>" << std::endl
509
              << Indent (level+2) << "</FailureDetails>" << std::endl;
510
        }
511
      for (uint32_t i = 0; i < test->m_children.size (); i++)
512
        {
513
          TestCase *child = test->m_children[i];
514
          PrintReport (child, os, xml, level + 1);
515
        }
516
      *os << Indent (level) << "</Test>" << std::endl;
517
    }
518
  else
519
    {
520
      *os << Indent (level) << statusString << " " << test->GetName () 
521
          << " " << real << "ms" << std::endl;
522
      if (m_verbose)
523
        {
524
          for (uint32_t i = 0; i < test->m_result->failure.size (); i++)
525
            {
526
              TestCaseFailure failure = test->m_result->failure[i];
527
              *os << Indent (level) << "    got=\"" << failure.cond << "\" expected=\"" 
528
                  << failure.actual << "\" in=\"" << failure.file << ":" << failure.line 
529
                  << "\" " << failure.message << std::endl;
530
            }
531
          for (uint32_t i = 0; i < test->m_children.size (); i++)
532
            {
533
              TestCase *child = test->m_children[i];
534
              PrintReport (child, os, xml, level + 1);
535
            }
536
        }
537
    }
538
}
539
  
540
void
541
TestRunnerImpl::PrintHelp (const char *program_name) const
542
{
543
  std::cout << "Usage: " << program_name << " [OPTIONS]" << std::endl
544
            << std::endl
545
            << "Options: "
546
            << "  --help                 : print these options" << std::endl
547
            << "  --print-test-name-list : print the list of names of tests available" << std::endl
548
            << "  --print-test-type-list : print the list of types of tests available" << std::endl
549
            << "  --print-temp-dir       : Print name of temporary directory before running the tests" << std::endl
550
            << "  --test-type=TYPE       : Process only tests of type TYPE" << std::endl
551
            << "  --test-name=NAME       : Process only test whose name matches NAME" << std::endl
552
            << "  --assert-on-failure    : when a test fails, crash immediately (useful" << std::endl
553
            << "                           when running under a debugger" << std::endl
554
            << "  --stop-on-failure      : when a test fails, stop immediately" << std::endl
555
            << "  --verbose              : Print details of test execution" << std::endl
556
            << "  --xml                  : format test run output as xml" << std::endl
557
            << "  --tempdir=DIR          : set temp dir for tests to store output files" << std::endl
558
            << "  --datadir=DIR          : set data dir for tests to read reference files" << std::endl
559
            << "  --out=FILE             : send test result to FILE instead of standard "
560
            << "output" << std::endl
561
            << "  --append=FILE          : append test result to FILE instead of standard "
562
            << "output" << std::endl
563
    ;  
564
}
565
566
void
567
TestRunnerImpl::PrintTestNameList (std::list<TestCase *>::const_iterator begin, 
568
                                   std::list<TestCase *>::const_iterator end) const
569
{
570
  for (std::list<TestCase *>::const_iterator i = begin; i != end; ++i)
571
    {
572
      TestCase *test = *i;
573
      std::cout << test->GetName () << std::endl;
574
    }
575
}
576
577
void
578
TestRunnerImpl::PrintTestTypeList (void) const
579
{
580
  std::cout << "  bvt:         Build Verification Tests (to see if build completed successfully)" << std::endl;
581
  std::cout << "  core:        Run all TestSuite-based tests (exclude examples)" << std::endl;
582
  std::cout << "  example:     Examples (to see if example programs run successfully)" << std::endl;
583
  std::cout << "  performance: Performance Tests (check to see if the system is as fast as expected)" << std::endl;
584
  std::cout << "  system:      System Tests (spans modules to check integration of modules)" << std::endl;
585
  std::cout << "  unit:        Unit Tests (within modules to check basic functionality)" << std::endl;
586
}
587
588
589
std::list<TestCase *>
590
TestRunnerImpl::FilterTests (std::string testName, enum TestSuite::Type testType) const
591
{
592
  std::list<TestCase *> tests;
593
  for (uint32_t i = 0; i < m_suites.size (); ++i)
594
    {
595
      TestSuite *test = m_suites[i];
596
      if (testType != TestSuite::ALL && test->GetTestType () != testType)
597
        {
598
          // skip test
599
          continue;
600
        }
601
      if (testName != "" && test->GetName () != testName)
602
        {
603
          // skip test
604
          continue;
605
        }
606
      tests.push_back (test);
607
    }
608
  return tests;
609
}
610
611
612
int 
613
TestRunnerImpl::Run (int argc, char *argv[])
614
{
615
  std::string testName = "";
616
  std::string testTypeString = "";
617
  std::string out = "";
618
  bool xml = false;
619
  bool append = false;
620
  bool printTempDir = false;
621
  bool printTestTypeList = false;
622
  bool printTestNameList = false;
623
  char *progname = argv[0];
624
625
  argv++;
626
627
  while (*argv != 0)
628
    {
629
      char *arg = *argv;
630
631
      if (strcmp(arg, "--assert-on-failure") == 0)
632
        {
633
          m_assertOnFailure = true;
634
        }
635
      else if (strcmp (arg, "--stop-on-failure") == 0)
636
        {
637
          m_continueOnFailure = false;
638
        }
639
      else if (strcmp (arg, "--verbose") == 0)
640
        {
641
          m_verbose = true;
642
        }
643
      else if (strcmp (arg, "--print-temp-dir") == 0)
644
        {
645
          printTempDir = true;
646
        }
647
      else if (strcmp (arg, "--update-data") == 0)
648
        {
649
          m_updateData = true;
650
        }
651
      else if (strcmp (arg, "--help") == 0)
652
        {
653
          PrintHelp (progname);
654
          return 0;
655
        }
656
      else if (strcmp (arg, "--print-test-name-list") == 0)
657
        {
658
          printTestNameList = true;
659
        }
660
      else if (strcmp (arg, "--print-test-type-list") == 0)
661
        {
662
          printTestTypeList = true;
663
        }
664
     else if (strcmp(arg, "--append") == 0)
665
        {
666
          append = true;
667
        }
668
      else if (strcmp(arg, "--xml") == 0)
669
        {
670
          xml = true;
671
        }
672
      else if (strncmp(arg, "--test-type=", strlen("--test-type=")) == 0)
673
        {
674
          testTypeString = arg + strlen("--test-type=");
675
        }
676
      else if (strncmp(arg, "--test-name=", strlen("--test-name=")) == 0)
677
        {
678
          testName = arg + strlen("--test-name=");
679
        }
680
      else if (strncmp(arg, "--tempdir=", strlen("--tempdir=")) == 0)
681
        {
682
          m_tempDir = arg + strlen("--tempdir=");
683
        }
684
      else if (strncmp(arg, "--out=", strlen("--out=")) == 0)
685
        {
686
          out = arg + strlen("--out=");
687
        }
688
      else
689
        {
690
          // un-recognized command-line argument
691
          PrintHelp (progname);
692
          return 0;
693
        }
694
      argv++;
695
    }
696
  enum TestSuite::Type testType;
697
  if (testTypeString == "")
698
    {
699
      testType = TestSuite::ALL;
700
    }
701
  else if (testTypeString == "bvt")
702
    {
703
      testType = TestSuite::BVT;
704
    }
705
  else if (testTypeString == "core")
706
    {
707
      testType = TestSuite::ALL;
708
    }
709
  else if (testTypeString == "example")
710
    {
711
      testType = TestSuite::EXAMPLE;
712
    }
713
  else if (testTypeString == "unit")
714
    {
715
      testType = TestSuite::UNIT;
716
    }
717
  else if (testTypeString == "system")
718
    {
719
      testType = TestSuite::SYSTEM;
720
    }
721
  else
722
    {
723
      std::cout << "Invalid test type specified: " << testTypeString << std::endl;
724
      PrintTestTypeList ();
725
      return 1;
726
    }
727
728
  std::list<TestCase *> tests = FilterTests (testName, testType);
729
730
  if (m_tempDir == "")
731
    {
732
      m_tempDir = SystemPath::MakeTemporaryDirectoryName ();
733
    }
734
  if (printTempDir)
735
    {
736
      std::cout << m_tempDir << std::endl;
737
    }
738
  if (printTestNameList)
739
    {
740
      PrintTestNameList (tests.begin (), tests.end ());
741
      return 0;
742
    }
743
  if (printTestTypeList)
744
    {
745
      PrintTestTypeList ();
746
      return 0;
747
    }
748
  
749
750
  std::ostream *os;
751
  if (out != "")
752
    {
753
      std::ofstream *ofs;
754
      ofs = new std::ofstream();
755
      std::ios_base::openmode mode = std::ios_base::out;
756
      if (append)
757
        {
758
          mode |= std::ios_base::app;
759
        }
760
      else
761
        {
762
          mode |= std::ios_base::trunc;
763
        }
764
      ofs->open (out.c_str (), mode);
765
      os = ofs;
766
    }
767
  else
768
    {
769
      os = &std::cout;
770
    }
771
772
  // let's run our tests now.
773
  bool failed = false;
774
  for (std::list<TestCase *>::const_iterator i = tests.begin (); i != tests.end (); ++i)
775
    {
776
      TestCase *test = *i;
777
      test->Run (this);
778
      PrintReport (test, os, xml, 0);
779
      if (test->IsFailed ())
780
        {
781
          failed = true;
782
          if (!m_continueOnFailure)
783
            {
784
              return 1;
785
            }
786
        }
787
    }
788
789
  if (out != "")
790
    {
791
      delete os;
792
    }
793
794
  return failed?1:0;
795
}
796
797
int 
798
TestRunner::Run (int argc, char *argv[])
799
{
800
  return TestRunnerImpl::Instance ()->Run (argc, argv);
770
}
801
}
771
802
772
} // namespace ns3
803
} // namespace ns3
(-)a/src/core/model/test.h (-659 / +341 lines)
 Lines 28-36    Link Here 
28
#include <limits>
28
#include <limits>
29
#include <stdint.h>
29
#include <stdint.h>
30
30
31
#include "ns3/system-wall-clock-ms.h"
31
#include "system-wall-clock-ms.h"
32
32
#include "deprecated.h"
33
extern bool gBreakOnFailure;
34
33
35
// 
34
// 
36
// Note on below macros:
35
// Note on below macros:
 Lines 42-55    Link Here 
42
// defining a robust macro.
41
// defining a robust macro.
43
//
42
//
44
43
45
/**
44
#define ASSERT_ON_FAILURE                       \
46
 * \brief Convenience macro to extract the source directory of the current 
45
  do {                                          \
47
 * source file.
46
    if (MustAssertOnFailure ())                 \
48
 *
47
      {                                         \
49
 * \see TestCase::GetSourceDir
48
        *(int *)0 = 0;                          \
50
 */
49
      }                                         \
51
#define NS_TEST_SOURCEDIR \
50
  } while (false)
52
  TestCase::GetSourceDir (__FILE__)
51
52
#define CONTINUE_ON_FAILURE                                             \
53
  do {                                                                  \
54
    if (!MustContinueOnFailure ())                                      \
55
      {                                                                 \
56
        return;                                                         \
57
      }                                                                 \
58
  } while (false)
59
60
#define CONTINUE_ON_FAILURE_RETURNS_BOOL                                \
61
  do {                                                                  \
62
    if (!MustContinueOnFailure ())                                      \
63
      {                                                                 \
64
        return IsStatusFailure ();                                      \
65
      }                                                                 \
66
  } while (false)
67
68
53
69
54
// ===========================================================================
70
// ===========================================================================
55
// Test for equality (generic version)
71
// Test for equality (generic version)
 Lines 58-82    Link Here 
58
/**
74
/**
59
 * \internal
75
 * \internal
60
 */
76
 */
61
#define NS_TEST_ASSERT_MSG_EQ_INTERNAL(actual, limit, msg, file, line)                                  \
77
#define NS_TEST_ASSERT_MSG_EQ_INTERNAL(actual, limit, msg, file, line)  \
62
  do {                                                                                                  \
78
  do {                                                                  \
63
      if (!((actual) == (limit)))                                                                         \
79
    if (!((actual) == (limit)))                                         \
64
        {                                                                                                 \
80
      {                                                                 \
65
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                           \
81
        ASSERT_ON_FAILURE;                                              \
66
          std::ostringstream msgStream;                                                                   \
82
        std::ostringstream msgStream;                                   \
67
          msgStream << msg;                                                                               \
83
        msgStream << msg;                                               \
68
          std::ostringstream actualStream;                                                                \
84
        std::ostringstream actualStream;                                \
69
          actualStream << actual;                                                                         \
85
        actualStream << actual;                                         \
70
          std::ostringstream limitStream;                                                                 \
86
        std::ostringstream limitStream;                                 \
71
          limitStream << limit;                                                                           \
87
        limitStream << limit;                                           \
72
          ReportTestFailure (std::string (# actual) + " (actual) == " + std::string (# limit) + " (limit)", \
88
        ReportTestFailure (std::string (#actual) + " (actual) == " +    \
73
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);          \
89
                           std::string (#limit) + " (limit)",           \
74
          if (!ContinueOnFailure ())                                                                      \
90
                           actualStream.str (), limitStream.str (),     \
75
            {                                                                                             \
91
                           msgStream.str (), file, line);               \
76
              return;                                                                                \
92
        CONTINUE_ON_FAILURE;                                            \
77
            }                                                                                             \
93
      }                                                                 \
78
        }                                                                                                 \
94
  } while (false)
79
    } while (false)
80
95
81
/**
96
/**
82
 * \brief Test that an actual and expected (limit) value are equal and report
97
 * \brief Test that an actual and expected (limit) value are equal and report
 Lines 110-134    Link Here 
110
/**
125
/**
111
 * \internal
126
 * \internal
112
 */
127
 */
113
#define NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL_INTERNAL(actual, limit, msg, file, line)                                  \
128
#define NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL_INTERNAL(actual, limit, msg, file, line) \
114
  do {                                                                                                  \
129
  do {                                                                  \
115
      if (!((actual) == (limit)))                                                                         \
130
    if (!((actual) == (limit)))                                         \
116
        {                                                                                                 \
131
      {                                                                 \
117
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                           \
132
        ASSERT_ON_FAILURE;                                              \
118
          std::ostringstream msgStream;                                                                   \
133
        std::ostringstream msgStream;                                   \
119
          msgStream << msg;                                                                               \
134
        msgStream << msg;                                               \
120
          std::ostringstream actualStream;                                                                \
135
        std::ostringstream actualStream;                                \
121
          actualStream << actual;                                                                         \
136
        actualStream << actual;                                         \
122
          std::ostringstream limitStream;                                                                 \
137
        std::ostringstream limitStream;                                 \
123
          limitStream << limit;                                                                           \
138
        limitStream << limit;                                           \
124
          ReportTestFailure (std::string (# actual) + " (actual) == " + std::string (# limit) + " (limit)", \
139
        ReportTestFailure (std::string (#actual) + " (actual) == " +        \
125
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);          \
140
                       std::string (#limit) + " (limit)",               \
126
          if (!ContinueOnFailure ())                                                                      \
141
                       actualStream.str (), limitStream.str (),         \
127
            {                                                                                             \
142
                       msgStream.str (), file, line);                   \
128
              return true;                                                                                \
143
        CONTINUE_ON_FAILURE_RETURNS_BOOL;                               \
129
            }                                                                                             \
144
      }                                                                 \
130
        }                                                                                                 \
145
  } while (false)
131
    } while (false)
132
146
133
/**
147
/**
134
 * \brief Test that an actual and expected (limit) value are equal and report
148
 * \brief Test that an actual and expected (limit) value are equal and report
 Lines 168-188    Link Here 
168
 * Required to avoid use of return statement which allows use in methods 
182
 * Required to avoid use of return statement which allows use in methods 
169
 * (esp. callbacks) returning void.
183
 * (esp. callbacks) returning void.
170
 */
184
 */
171
#define NS_TEST_EXPECT_MSG_EQ_INTERNAL(actual, limit, msg, file, line)                                  \
185
#define NS_TEST_EXPECT_MSG_EQ_INTERNAL(actual, limit, msg, file, line)  \
172
  do {                                                                                                  \
186
  do {                                                                  \
173
      if (!((actual) == (limit)))                                                                         \
187
    if (!((actual) == (limit)))                                         \
174
        {                                                                                                 \
188
      {                                                                 \
175
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                           \
189
        ASSERT_ON_FAILURE;                                              \
176
          std::ostringstream msgStream;                                                                   \
190
        std::ostringstream msgStream;                                   \
177
          msgStream << msg;                                                                               \
191
        msgStream << msg;                                               \
178
          std::ostringstream actualStream;                                                                \
192
        std::ostringstream actualStream;                                \
179
          actualStream << actual;                                                                         \
193
        actualStream << actual;                                         \
180
          std::ostringstream limitStream;                                                                 \
194
        std::ostringstream limitStream;                                 \
181
          limitStream << limit;                                                                           \
195
        limitStream << limit;                                           \
182
          ReportTestFailure (std::string (# actual) + " (actual) == " + std::string (# limit) + " (limit)", \
196
        ReportTestFailure (std::string (#actual) + " (actual) == " +        \
183
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);          \
197
                       std::string (#limit) + " (limit)",               \
184
        }                                                                                                 \
198
                       actualStream.str (), limitStream.str (),         \
185
    } while (false)
199
                       msgStream.str (), file, line);                   \
200
      }                                                                 \
201
  } while (false)
186
202
187
/**
203
/**
188
 * \brief Test that an actual and expected (limit) value are equal and report
204
 * \brief Test that an actual and expected (limit) value are equal and report
 Lines 221-247    Link Here 
221
/**
237
/**
222
 * \internal
238
 * \internal
223
 */
239
 */
224
#define NS_TEST_ASSERT_MSG_EQ_TOL_INTERNAL(actual, limit, tol, msg, file, line)                                       \
240
#define NS_TEST_ASSERT_MSG_EQ_TOL_INTERNAL(actual, limit, tol, msg, file, line) \
225
  do {                                                                                                                \
241
  do {                                                                  \
226
      if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol))                                                     \
242
    if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol))       \
227
        {                                                                                                               \
243
      {                                                                 \
228
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                                         \
244
        ASSERT_ON_FAILURE;                                              \
229
          std::ostringstream msgStream;                                                                                 \
245
        std::ostringstream msgStream;                                   \
230
          msgStream << msg;                                                                                             \
246
        msgStream << msg;                                               \
231
          std::ostringstream actualStream;                                                                              \
247
        std::ostringstream actualStream;                                \
232
          actualStream << actual;                                                                                       \
248
        actualStream << actual;                                         \
233
          std::ostringstream limitStream;                                                                               \
249
        std::ostringstream limitStream;                                 \
234
          limitStream << limit << " +- " << tol;                                                                        \
250
        limitStream << limit << " +- " << tol;                          \
235
          std::ostringstream condStream;                                                                                \
251
        std::ostringstream condStream;                                  \
236
          condStream << # actual << " (actual) < " << # limit << " (limit) + " << # tol << " (tol) && " <<                 \
252
        condStream << #actual << " (actual) < " << #limit               \
237
          # actual << " (actual) > " << # limit << " (limit) - " << # tol << " (tol)";                       \
253
                   << " (limit) + " << #tol << " (tol) && "             \
238
          ReportTestFailure (condStream.str (), actualStream.str (), limitStream.str (), msgStream.str (), file, line); \
254
                   << #actual << " (actual) > " << #limit               \
239
          if (!ContinueOnFailure ())                                                                                    \
255
                   << " (limit) - " << #tol << " (tol)";                \
240
            {                                                                                                           \
256
        ReportTestFailure (condStream.str (), actualStream.str (),          \
241
              return;                                                                                              \
257
                       limitStream.str (), msgStream.str (),            \
242
            }                                                                                                           \
258
                       file, line);                                     \
243
        }                                                                                                               \
259
        CONTINUE_ON_FAILURE;                                            \
244
    } while (false)
260
      }                                                                 \
261
  } while (false)
245
262
246
/**
263
/**
247
 * \brief Test that actual and expected (limit) values are equal to plus or minus
264
 * \brief Test that actual and expected (limit) values are equal to plus or minus
 Lines 297-323    Link Here 
297
/**
314
/**
298
 * \internal
315
 * \internal
299
 */
316
 */
300
#define NS_TEST_ASSERT_MSG_EQ_TOL_RETURNS_BOOL_INTERNAL(actual, limit, tol, msg, file, line)                                       \
317
#define NS_TEST_ASSERT_MSG_EQ_TOL_RETURNS_BOOL_INTERNAL(actual, limit, tol, msg, file, line) \
301
  do {                                                                                                                \
318
  do {                                                                  \
302
      if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol))                                                     \
319
    if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol))       \
303
        {                                                                                                               \
320
      {                                                                 \
304
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                                         \
321
        ASSERT_ON_FAILURE;                                              \
305
          std::ostringstream msgStream;                                                                                 \
322
        std::ostringstream msgStream;                                   \
306
          msgStream << msg;                                                                                             \
323
        msgStream << msg;                                               \
307
          std::ostringstream actualStream;                                                                              \
324
        std::ostringstream actualStream;                                \
308
          actualStream << actual;                                                                                       \
325
        actualStream << actual;                                         \
309
          std::ostringstream limitStream;                                                                               \
326
        std::ostringstream limitStream;                                 \
310
          limitStream << limit << " +- " << tol;                                                                        \
327
        limitStream << limit << " +- " << tol;                          \
311
          std::ostringstream condStream;                                                                                \
328
        std::ostringstream condStream;                                  \
312
          condStream << # actual << " (actual) < " << # limit << " (limit) + " << # tol << " (tol) && " <<                 \
329
        condStream << #actual << " (actual) < " << #limit               \
313
          # actual << " (actual) > " << # limit << " (limit) - " << # tol << " (tol)";                       \
330
                   << " (limit) + " << #tol << " (tol) && "             \
314
          ReportTestFailure (condStream.str (), actualStream.str (), limitStream.str (), msgStream.str (), file, line); \
331
                   << #actual << " (actual) > " << #limit               \
315
          if (!ContinueOnFailure ())                                                                                    \
332
                   << " (limit) - " << #tol << " (tol)";                \
316
            {                                                                                                           \
333
        ReportTestFailure (condStream.str (), actualStream.str (),          \
317
              return true;                                                                                              \
334
                       limitStream.str (), msgStream.str (),            \
318
            }                                                                                                           \
335
                       file, line);                                     \
319
        }                                                                                                               \
336
        CONTINUE_ON_FAILURE_RETURNS_BOOL;                               \
320
    } while (false)
337
      }                                                                 \
338
  } while (false)
321
339
322
/**
340
/**
323
 * \brief Test that actual and expected (limit) values are equal to plus or minus
341
 * \brief Test that actual and expected (limit) values are equal to plus or minus
 Lines 379-401    Link Here 
379
 * Required to avoid use of return statement which allows use in methods 
397
 * Required to avoid use of return statement which allows use in methods 
380
 * (esp. callbacks) returning void.
398
 * (esp. callbacks) returning void.
381
 */
399
 */
382
#define NS_TEST_EXPECT_MSG_EQ_TOL_INTERNAL(actual, limit, tol, msg, file, line)                                       \
400
#define NS_TEST_EXPECT_MSG_EQ_TOL_INTERNAL(actual, limit, tol, msg, file, line) \
383
  do {                                                                                                                \
401
  do {                                                                  \
384
      if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol))                                                     \
402
    if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol))       \
385
        {                                                                                                               \
403
      {                                                                 \
386
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                                         \
404
        ASSERT_ON_FAILURE;                                              \
387
          std::ostringstream msgStream;                                                                                 \
405
        std::ostringstream msgStream;                                   \
388
          msgStream << msg;                                                                                             \
406
        msgStream << msg;                                               \
389
          std::ostringstream actualStream;                                                                              \
407
        std::ostringstream actualStream;                                \
390
          actualStream << actual;                                                                                       \
408
        actualStream << actual;                                         \
391
          std::ostringstream limitStream;                                                                               \
409
        std::ostringstream limitStream;                                 \
392
          limitStream << limit << " +- " << tol;                                                                        \
410
        limitStream << limit << " +- " << tol;                          \
393
          std::ostringstream condStream;                                                                                \
411
        std::ostringstream condStream;                                  \
394
          condStream << # actual << " (actual) < " << # limit << " (limit) + " << # tol << " (tol) && " <<                 \
412
        condStream << #actual << " (actual) < " << #limit               \
395
          # actual << " (actual) > " << # limit << " (limit) - " << # tol << " (tol)";                       \
413
                   << " (limit) + " << #tol << " (tol) && "             \
396
          ReportTestFailure (condStream.str (), actualStream.str (), limitStream.str (), msgStream.str (), file, line); \
414
                   << #actual << " (actual) > " << #limit               \
397
        }                                                                                                               \
415
                   << " (limit) - " << #tol << " (tol)";                \
398
    } while (false)
416
        ReportTestFailure (condStream.str (), actualStream.str (),          \
417
                       limitStream.str (), msgStream.str (),            \
418
                       file, line);                                     \
419
      }                                                                 \
420
  } while (false)
399
421
400
/**
422
/**
401
 * \brief Test that actual and expected (limit) values are equal to plus or minus
423
 * \brief Test that actual and expected (limit) values are equal to plus or minus
 Lines 455-479    Link Here 
455
/**
477
/**
456
 * \internal
478
 * \internal
457
 */
479
 */
458
#define NS_TEST_ASSERT_MSG_NE_INTERNAL(actual, limit, msg, file, line)                                  \
480
#define NS_TEST_ASSERT_MSG_NE_INTERNAL(actual, limit, msg, file, line)  \
459
  do {                                                                                                  \
481
  do {                                                                  \
460
      if (!((actual) != (limit)))                                                                         \
482
    if (!((actual) != (limit)))                                         \
461
        {                                                                                                 \
483
      {                                                                 \
462
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                           \
484
        ASSERT_ON_FAILURE;                                              \
463
          std::ostringstream msgStream;                                                                   \
485
        std::ostringstream msgStream;                                   \
464
          msgStream << msg;                                                                               \
486
        msgStream << msg;                                               \
465
          std::ostringstream actualStream;                                                                \
487
        std::ostringstream actualStream;                                \
466
          actualStream << actual;                                                                         \
488
        actualStream << actual;                                         \
467
          std::ostringstream limitStream;                                                                 \
489
        std::ostringstream limitStream;                                 \
468
          limitStream << limit;                                                                           \
490
        limitStream << limit;                                           \
469
          ReportTestFailure (std::string (# actual) + " (actual) != " + std::string (# limit) + " (limit)", \
491
        ReportTestFailure (std::string (#actual) + " (actual) != " +        \
470
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);          \
492
                       std::string (#limit) + " (limit)",               \
471
          if (!ContinueOnFailure ())                                                                      \
493
                       actualStream.str (), limitStream.str (),         \
472
            {                                                                                             \
494
                       msgStream.str (), file, line);                   \
473
              return;                                                                                \
495
        CONTINUE_ON_FAILURE;                                            \
474
            }                                                                                             \
496
      }                                                                 \
475
        }                                                                                                 \
497
  } while (false)
476
    } while (false)
477
498
478
/**
499
/**
479
 * \brief Test that an actual and expected (limit) value are equal and report
500
 * \brief Test that an actual and expected (limit) value are equal and report
 Lines 506-530    Link Here 
506
/**
527
/**
507
 * \internal
528
 * \internal
508
 */
529
 */
509
#define NS_TEST_ASSERT_MSG_NE_RETURNS_BOOL_INTERNAL(actual, limit, msg, file, line)                                  \
530
#define NS_TEST_ASSERT_MSG_NE_RETURNS_BOOL_INTERNAL(actual, limit, msg, file, line) \
510
  do {                                                                                                  \
531
  do {                                                                  \
511
      if (!((actual) != (limit)))                                                                         \
532
    if (!((actual) != (limit)))                                         \
512
        {                                                                                                 \
533
      {                                                                 \
513
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                           \
534
        ASSERT_ON_FAILURE;                                              \
514
          std::ostringstream msgStream;                                                                   \
535
        std::ostringstream msgStream;                                   \
515
          msgStream << msg;                                                                               \
536
        msgStream << msg;                                               \
516
          std::ostringstream actualStream;                                                                \
537
        std::ostringstream actualStream;                                \
517
          actualStream << actual;                                                                         \
538
        actualStream << actual;                                         \
518
          std::ostringstream limitStream;                                                                 \
539
        std::ostringstream limitStream;                                 \
519
          limitStream << limit;                                                                           \
540
        limitStream << limit;                                           \
520
          ReportTestFailure (std::string (# actual) + " (actual) != " + std::string (# limit) + " (limit)", \
541
        ReportTestFailure (std::string (#actual) + " (actual) != " +        \
521
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);          \
542
                       std::string (#limit) + " (limit)",               \
522
          if (!ContinueOnFailure ())                                                                      \
543
                       actualStream.str (), limitStream.str (),         \
523
            {                                                                                             \
544
                       msgStream.str (), file, line);                   \
524
              return true;                                                                                \
545
        CONTINUE_ON_FAILURE_RETURNS_BOOL;                               \
525
            }                                                                                             \
546
      }                                                                 \
526
        }                                                                                                 \
547
  } while (false)
527
    } while (false)
528
548
529
/**
549
/**
530
 * \brief Test that an actual and expected (limit) value are equal and report
550
 * \brief Test that an actual and expected (limit) value are equal and report
 Lines 563-583    Link Here 
563
 * Required to avoid use of return statement which allows use in methods 
583
 * Required to avoid use of return statement which allows use in methods 
564
 * (callbacks) returning void.
584
 * (callbacks) returning void.
565
 */
585
 */
566
#define NS_TEST_EXPECT_MSG_NE_INTERNAL(actual, limit, msg, file, line)                                  \
586
#define NS_TEST_EXPECT_MSG_NE_INTERNAL(actual, limit, msg, file, line)  \
567
  do {                                                                                                  \
587
  do {                                                                  \
568
      if (!((actual) != (limit)))                                                                         \
588
    if (!((actual) != (limit)))                                         \
569
        {                                                                                                 \
589
      {                                                                 \
570
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                           \
590
        ASSERT_ON_FAILURE;                                              \
571
          std::ostringstream msgStream;                                                                   \
591
        std::ostringstream msgStream;                                   \
572
          msgStream << msg;                                                                               \
592
        msgStream << msg;                                               \
573
          std::ostringstream actualStream;                                                                \
593
        std::ostringstream actualStream;                                \
574
          actualStream << actual;                                                                         \
594
        actualStream << actual;                                         \
575
          std::ostringstream limitStream;                                                                 \
595
        std::ostringstream limitStream;                                 \
576
          limitStream << limit;                                                                           \
596
        limitStream << limit;                                           \
577
          ReportTestFailure (std::string (# actual) + " (actual) != " + std::string (# limit) + " (limit)", \
597
        ReportTestFailure (std::string (#actual) + " (actual) != " +        \
578
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);          \
598
                       std::string (#limit) + " (limit)",               \
579
        }                                                                                                 \
599
                       actualStream.str (), limitStream.str (),         \
580
    } while (false)
600
                       msgStream.str (), file, line);                   \
601
      }                                                                 \
602
  } while (false)
581
603
582
/**
604
/**
583
 * \brief Test that an actual and expected (limit) value are equal and report
605
 * \brief Test that an actual and expected (limit) value are equal and report
 Lines 614-638    Link Here 
614
/**
636
/**
615
 * \internal
637
 * \internal
616
 */
638
 */
617
#define NS_TEST_ASSERT_MSG_LT_INTERNAL(actual, limit, msg, file, line)                                   \
639
#define NS_TEST_ASSERT_MSG_LT_INTERNAL(actual, limit, msg, file, line)  \
618
  do {                                                                                                   \
640
  do {                                                                  \
619
      if (!((actual) < (limit)))                                                                           \
641
    if (!((actual) < (limit)))                                          \
620
        {                                                                                                  \
642
      {                                                                 \
621
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                            \
643
        ASSERT_ON_FAILURE;                                              \
622
          std::ostringstream msgStream;                                                                    \
644
        std::ostringstream msgStream;                                   \
623
          msgStream << msg;                                                                                \
645
        msgStream << msg;                                               \
624
          std::ostringstream actualStream;                                                                 \
646
        std::ostringstream actualStream;                                \
625
          actualStream << actual;                                                                          \
647
        actualStream << actual;                                         \
626
          std::ostringstream limitStream;                                                                  \
648
        std::ostringstream limitStream;                                 \
627
          limitStream << limit;                                                                            \
649
        limitStream << limit;                                           \
628
          ReportTestFailure (std::string (# actual) + " (actual) < " + std::string (# limit) + " (limit)",   \
650
        ReportTestFailure (std::string (#actual) + " (actual) < " +         \
629
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);           \
651
                       std::string (#limit) + " (limit)",               \
630
          if (!ContinueOnFailure ())                                                                       \
652
                       actualStream.str (), limitStream.str (),         \
631
            {                                                                                              \
653
                       msgStream.str (), file, line);                   \
632
              return;                                                                                 \
654
        CONTINUE_ON_FAILURE;                                            \
633
            }                                                                                              \
655
      }                                                                 \
634
        }                                                                                                  \
656
  } while (false)
635
    } while (false)
636
657
637
/**
658
/**
638
 * \brief Test that an actual value is less than a limit and report and abort
659
 * \brief Test that an actual value is less than a limit and report and abort
 Lines 658-678    Link Here 
658
 * Required to avoid use of return statement which allows use in methods 
679
 * Required to avoid use of return statement which allows use in methods 
659
 * (callbacks) returning void.
680
 * (callbacks) returning void.
660
 */
681
 */
661
#define NS_TEST_EXPECT_MSG_LT_INTERNAL(actual, limit, msg, file, line)                                   \
682
#define NS_TEST_EXPECT_MSG_LT_INTERNAL(actual, limit, msg, file, line)  \
662
  do {                                                                                                   \
683
  do {                                                                  \
663
      if (!((actual) < (limit)))                                                                           \
684
    if (!((actual) < (limit)))                                          \
664
        {                                                                                                  \
685
      {                                                                 \
665
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                            \
686
        ASSERT_ON_FAILURE;                                              \
666
          std::ostringstream msgStream;                                                                    \
687
        std::ostringstream msgStream;                                   \
667
          msgStream << msg;                                                                                \
688
        msgStream << msg;                                               \
668
          std::ostringstream actualStream;                                                                 \
689
        std::ostringstream actualStream;                                \
669
          actualStream << actual;                                                                          \
690
        actualStream << actual;                                         \
670
          std::ostringstream limitStream;                                                                  \
691
        std::ostringstream limitStream;                                 \
671
          limitStream << limit;                                                                            \
692
        limitStream << limit;                                           \
672
          ReportTestFailure (std::string (# actual) + " (actual) < " + std::string (# limit) + " (limit)",   \
693
        ReportTestFailure (std::string (#actual) + " (actual) < " +         \
673
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);           \
694
                       std::string (#limit) + " (limit)",               \
674
        }                                                                                                  \
695
                       actualStream.str (), limitStream.str (),         \
675
    } while (false)
696
                       msgStream.str (), file, line);                   \
697
      }                                                                 \
698
  } while (false)
676
699
677
/**
700
/**
678
 * \brief Test that an actual value is less than a limit and report if not.
701
 * \brief Test that an actual value is less than a limit and report if not.
 Lines 698-722    Link Here 
698
/**
721
/**
699
 * \internal
722
 * \internal
700
 */
723
 */
701
#define NS_TEST_ASSERT_MSG_GT_INTERNAL(actual, limit, msg, file, line)                                   \
724
#define NS_TEST_ASSERT_MSG_GT_INTERNAL(actual, limit, msg, file, line)  \
702
  do {                                                                                                   \
725
  do {                                                                  \
703
      if (!((actual) > (limit)))                                                                           \
726
    if (!((actual) > (limit)))                                          \
704
        {                                                                                                  \
727
      {                                                                 \
705
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                            \
728
        ASSERT_ON_FAILURE;                                              \
706
          std::ostringstream msgStream;                                                                    \
729
        std::ostringstream msgStream;                                   \
707
          msgStream << msg;                                                                                \
730
        msgStream << msg;                                               \
708
          std::ostringstream actualStream;                                                                 \
731
        std::ostringstream actualStream;                                \
709
          actualStream << actual;                                                                          \
732
        actualStream << actual;                                         \
710
          std::ostringstream limitStream;                                                                  \
733
        std::ostringstream limitStream;                                 \
711
          limitStream << limit;                                                                            \
734
        limitStream << limit;                                           \
712
          ReportTestFailure (std::string (# actual) + " (actual) > " + std::string (# limit) + " (limit)",   \
735
        ReportTestFailure (std::string (#actual) + " (actual) > " +         \
713
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);           \
736
                       std::string (#limit) + " (limit)",               \
714
          if (!ContinueOnFailure ())                                                                       \
737
                       actualStream.str (), limitStream.str (),         \
715
            {                                                                                              \
738
                       msgStream.str (), file, line);                   \
716
              return;                                                                                 \
739
        CONTINUE_ON_FAILURE;                                            \
717
            }                                                                                              \
740
      }                                                                 \
718
        }                                                                                                  \
741
  } while (false)
719
    } while (false)
720
742
721
/**
743
/**
722
 * \brief Test that an actual value is greater than a limit and report and abort
744
 * \brief Test that an actual value is greater than a limit and report and abort
 Lines 742-762    Link Here 
742
 * Required to avoid use of return statement which allows use in methods 
764
 * Required to avoid use of return statement which allows use in methods 
743
 * (callbacks) returning void.
765
 * (callbacks) returning void.
744
 */
766
 */
745
#define NS_TEST_EXPECT_MSG_GT_INTERNAL(actual, limit, msg, file, line)                                   \
767
#define NS_TEST_EXPECT_MSG_GT_INTERNAL(actual, limit, msg, file, line)  \
746
  do {                                                                                                   \
768
  do {                                                                  \
747
      if (!((actual) > (limit)))                                                                           \
769
    if (!((actual) > (limit)))                                          \
748
        {                                                                                                  \
770
      {                                                                 \
749
          if (gBreakOnFailure) { *(int *)0 = 0; }                                                            \
771
        ASSERT_ON_FAILURE;                                               \
750
          std::ostringstream msgStream;                                                                    \
772
        std::ostringstream msgStream;                                   \
751
          msgStream << msg;                                                                                \
773
        msgStream << msg;                                               \
752
          std::ostringstream actualStream;                                                                 \
774
        std::ostringstream actualStream;                                \
753
          actualStream << actual;                                                                          \
775
        actualStream << actual;                                         \
754
          std::ostringstream limitStream;                                                                  \
776
        std::ostringstream limitStream;                                 \
755
          limitStream << limit;                                                                            \
777
        limitStream << limit;                                           \
756
          ReporTesttFailure (std::string (# actual) + " (actual) > " + std::string (# limit) + " (limit)",   \
778
        ReportTestFailure (std::string (#actual) + " (actual) > " +      \
757
                             actualStream.str (), limitStream.str (), msgStream.str (), file, line);           \
779
                       std::string (#limit) + " (limit)",               \
758
        }                                                                                                  \
780
                       actualStream.str (), limitStream.str (),         \
759
    } while (false)
781
                       msgStream.str (), file, line);                   \
782
      }                                                                 \
783
  } while (false)
760
784
761
/**
785
/**
762
 * \brief Test that an actual value is greater than a limit and report if not.
786
 * \brief Test that an actual value is greater than a limit and report if not.
 Lines 795-1050    Link Here 
795
 * \param epsilon The second of double precision floating point numberss to compare
819
 * \param epsilon The second of double precision floating point numberss to compare
796
 * \returns Returns true if the doubles are equal to a precision defined by epsilon
820
 * \returns Returns true if the doubles are equal to a precision defined by epsilon
797
 */
821
 */
798
bool TestDoubleIsEqual (const double a, const double b, const double epsilon = std::numeric_limits<double>::epsilon ());
822
bool TestDoubleIsEqual (const double a, const double b, 
823
                        const double epsilon = std::numeric_limits<double>::epsilon ());
824
825
class TestRunnerImpl;
799
826
800
/**
827
/**
801
 * \brief A single test case.
828
 * \brief encapsulates test code
829
 *
830
 * To allow a new test to be run within the ns-3 test framework, users
831
 * need to create subclasses of this base class, override the DoRun method,
832
 * and use the NS_TEST_* macros within DoRun.
802
 */
833
 */
803
class TestCase
834
class TestCase
804
{
835
{
805
public:
836
public:
806
  TestCase (std::string name);
807
  virtual ~TestCase ();
837
  virtual ~TestCase ();
808
838
809
  /**
810
   * \brief Run this test case.
811
   */
812
  void Run (void);
813
814
  /**
815
   * \brief Set the verbosity of this test case.
816
   * \param verbose Whether or not to turn on any output the
817
   *                test case may provide.
818
   */
819
  void SetVerbose (bool verbose);
820
821
  /**
822
   * \brief Tell the test case whether or not to continue testing if an error is
823
   * detected.
824
   *
825
   * Typically, test cases depend on some number of individual tests.  Often, 
826
   * these tests build on functionality that has been previously verified.  In 
827
   * this case, subsequent test failures may simply be alternate manifestations
828
   * of previously detected errors.  Some developers may only be interested in 
829
   * seeing the first failure.  Other developers may want to see all the 
830
   * information they can get, and want to see all failures.  This is a matter
831
   * of individual preference, so we allow this behavior to be configured.
832
   *
833
   * \param continueOnFailure If true, run tests after a failure has been 
834
   *                          detected, otherwise stop on the first error.
835
   */
836
  void SetContinueOnFailure (bool continueOnFailure);
837
838
  /**
839
   * \brief Set the name of this test case.
840
   */
841
  void SetName (std::string name);
842
843
  /**
844
   * \brief Get the name of this test case.
845
   */
846
  std::string GetName (void);
847
848
  /**
849
   * \brief Set the base directory of the ns-3 distribution.
850
   */
851
  void SetBaseDir (std::string dir);
852
853
  /**
854
   * \brief Get the base directory of the ns-3 distribution.
855
   */
856
  std::string GetBaseDir (void);
857
858
  /**
859
   * \brief Set the temporary file directory (where to write temporary files).
860
   */
861
  void SetTempDir (std::string dir);
862
863
  /**
864
   * \brief Get the temporary file directory .
865
   */
866
  std::string GetTempDir (void);
867
868
/**
869
 * \brief Get the source directory of the current source file.
870
 *
871
 * One of the basic models of the test environment is that dedicated test- 
872
 * and response vectors live in the same directory as the source file.  So it 
873
 * is a common operation to figure out what directory a given source file lives
874
 * in.
875
 *
876
 * __FILE__ provides almost all of what we need, but in the gnu toolchain it 
877
 * comes out as something like "../src/core/pcap-file-test-suite.cc".
878
 * 
879
 * We really don't want to have any dependency on the directory out of which a
880
 * test is run, so we ask that any test-runner give us the base directory of the 
881
 * distribution, which is set via TestCase::SetBaseDir().  That string will look 
882
 * something like "/home/user/repos/ns-3-allinone/ns-3-dev".
883
 *
884
 * This function stitches the two pieces together and removes the file name to 
885
 * return something like "/home/user/repos/ns-3-allinone/ns-3-dev/src/core/".
886
 *
887
 * \param file The current source file name relative to the base directory.
888
 * \returns The current source directory.
889
 *
890
 * \warning Always call this function as GetSourceDir (__FILE__) or use the 
891
 * convenience macro NS_TEST_SOURCEDIR.
892
 */
893
  std::string GetSourceDir (std::string file);
894
895
  /**
896
   * \brief Set the stream to which status and result messages will be written.
897
   *
898
   * We really don't want to have to pass an ofstream around to every function
899
   * and we especially don't want to have to make our clients plumb an ofstream
900
   * around so we need to save it.  Since file streams are not designed to be
901
   * copied or assigned (what does it mean to have duplicate streams to a file) 
902
   * we have to stash a pointer to the stream.
903
   *
904
   * \param ofs output file stream
905
   */
906
  void SetStream (std::ofstream *ofs);
907
908
  /**
909
   * \brief Get the stream to which status and result messages will be written.
910
   */
911
  std::ofstream *GetStream (void);
912
913
  /**
914
   * \brief Manually update the error status of this test case.
915
   *
916
   * This does a logical OR of the error argument with the current error status.
917
   * If the argument is false, it does nothing.  If the argument is true, it 
918
   * sets the error status to "an error has occurred."
919
   *
920
   * \param error The status to use to update the test case error status
921
   */
922
  void UpdateErrorStatus (bool error);
923
924
  /**
925
   * \brief Manually set the error status of this test case.
926
   *
927
   * This sets the current error status to the argument provided.  Can be used
928
   * to reset any previous errors if the argument is false.
929
   *
930
   * \param error The status to use to set the test case error status
931
   */
932
  void SetErrorStatus (bool error);
933
934
  /**
935
   * \brief Get the error status of this test case.
936
   */
937
  bool GetErrorStatus (void);
938
939
  /**
940
   * \brief Should test cases continue running in the presence of errors?
941
   * \returns True if the test case should continue, false otherwise.
942
   */
943
  bool ContinueOnFailure (void);
944
945
  /**
946
   * \brief Issue a test report than the test suite has started running.
947
   */
948
  void ReportStart (void);
949
950
  /**
951
   * \brief Issue a test report than the test case has declared success.
952
   */
953
  void ReportCaseSuccess (void);
954
955
  /**
956
   * \brief Issue a test report than the test case has declared failure.
957
   */
958
  void ReportCaseFailure (void);
959
960
  /**
961
   * \brief Issue a test report than the test case has found an error and
962
   * report the details.
963
   */
964
  void ReportTestFailure (std::string cond, std::string actual, std::string limit, std::string message, 
965
                          std::string file, int32_t line);
966
967
  /**
968
   * \brief Issue a test report than the test case has completed its run.
969
   */
970
  void ReportEnd (void);
971
972
protected:
839
protected:
973
  /**
840
  /**
974
   * \internal
841
   * \param name the name of the new test created
975
   * \brief Implementation of reporting method for the start of the test case.
976
   */
842
   */
977
  virtual void DoReportStart (void);
843
  TestCase (std::string name);
978
844
979
  /**
845
  /**
980
   * \internal
846
   * \brief Add an individual test case to this test suite.
981
   * \brief Implementation of reporting method for success of the test case.
847
   *
848
   * \param testCase Pointer to the test case object to be added.
982
   */
849
   */
983
  virtual void DoReportCaseSuccess (void);
850
  void AddTestCase (TestCase *testCase);
984
851
985
  /**
852
  /**
986
   * \internal
853
   * \param directory the directory where the test data is located
987
   * \brief Implementation of reporting method for failure of the test case.
854
   *
855
   * In general, this method is invoked as SetDataDir (NS_TEST_SOURCEDIR);
988
   */
856
   */
989
  virtual void DoReportCaseFailure (void);
857
  void SetDataDir (std::string directory);
990
858
991
  /**
859
  /**
992
   * \internal
860
   * This method is deprecated. IsStatusFailure replaces it.
993
   * \brief Implementation of reporting method for failure of the test case.
994
   */
861
   */
995
  virtual void DoReportTestFailure (std::string cond, std::string actual, std::string limit, std::string message, 
862
  bool GetErrorStatus (void) const NS_DEPRECATED;
996
                                    std::string file, int32_t line);
863
  /**
864
   * \return true if the tests have failed, false otherwise.
865
   */
866
  bool IsStatusFailure (void) const;
867
  /**
868
   * \return true if the tests have succeeded, false otherwise.
869
   */
870
  bool IsStatusSuccess (void) const;
871
872
  // The methods below are used only by test macros and should not
873
  // be used by normal users.
874
  void ReportTestFailure (std::string cond, std::string actual, 
875
                      std::string limit, std::string message, 
876
                      std::string file, int32_t line);
877
  bool MustAssertOnFailure (void) const;
878
  bool MustContinueOnFailure (void) const;
879
  std::string CreateDataDirFilename (std::string filename);
880
  std::string CreateTempDirFilename (std::string filename);
881
private:
882
  friend class TestRunnerImpl;
997
883
998
  /**
884
  /**
999
   * \internal
1000
   * \brief Implementation of reporting method for the end of the test case.
1001
   */
1002
  virtual void DoReportEnd (void);
1003
1004
  /**
1005
   * \internal
1006
   * \brief Implementation to do any local setup required for this test case.
885
   * \brief Implementation to do any local setup required for this test case.
886
   *
887
   * Subclasses should override this method to perform any costly per-test setup
888
   * before DoRun is invoked.
1007
   */
889
   */
1008
  virtual void DoSetup (void);
890
  virtual void DoSetup (void);
1009
891
1010
  /**
892
  /**
1011
   * \internal
1012
   * \brief Implementation to actually run this test case.
893
   * \brief Implementation to actually run this test case.
894
   *
895
   * Subclasses should override this method to conduct their tests.
1013
   */
896
   */
1014
  virtual void DoRun (void) = 0;
897
  virtual void DoRun (void) = 0;
1015
898
1016
  /**
899
  /**
1017
   * \internal
1018
   * \brief Implementation to do any local setup required for this test case.
900
   * \brief Implementation to do any local setup required for this test case.
901
   *
902
   * Subclasses should override this method to perform any costly per-test teardown
1019
   */
903
   */
1020
  virtual void DoTeardown (void);
904
  virtual void DoTeardown (void);
1021
905
1022
private:
906
  // forbid copying objects
1023
  TestCase (TestCase& tc);
907
  TestCase (TestCase& tc);
1024
  TestCase& operator= (TestCase& tc);
908
  TestCase& operator= (TestCase& tc);
1025
909
1026
  SystemWallClockMs m_msClock;
910
  // methods called by TestRunnerImpl
911
  void Run (TestRunnerImpl *runner);
912
  std::string GetName (void) const;
913
  bool IsFailed (void) const;
914
915
916
  struct Result;
917
918
  TestCase *m_parent;
919
  std::vector<TestCase *> m_children;
920
  std::string m_dataDir;
921
  TestRunnerImpl *m_runner;
922
  struct Result *m_result;
1027
  std::string m_name;
923
  std::string m_name;
1028
  bool m_verbose;
1029
  bool m_continueOnFailure;
1030
  bool m_detailsReported;
1031
  std::string m_basedir;
1032
  std::string m_tempdir;
1033
  std::ofstream *m_ofs;
1034
  bool m_error;
1035
};
924
};
1036
925
1037
/**
926
/**
1038
 * \brief A suite of tests to run.
927
 * \brief A suite of tests to run.
1039
 */
928
 */
1040
class TestSuite
929
class TestSuite : public TestCase
1041
{
930
{
1042
public:
931
public:
1043
  /**
932
  /**
1044
   * \enum TestType
933
   * \enum TestType
1045
   * \brief Type of test.
934
   * \brief Type of test.
1046
   */
935
   */
1047
  enum TestType {
936
  enum Type {
937
    ALL = 0,
1048
    BVT = 1,    /**< This test suite implements a Build Verification Test */
938
    BVT = 1,    /**< This test suite implements a Build Verification Test */
1049
    UNIT,       /**< This test suite implements a Unit Test */
939
    UNIT,       /**< This test suite implements a Unit Test */
1050
    SYSTEM,     /**< This test suite implements a System Test */
940
    SYSTEM,     /**< This test suite implements a System Test */
 Lines 1058-1283    Link Here 
1058
   * \param name The name of the test suite.
948
   * \param name The name of the test suite.
1059
   * \param type The TestType of the test suite (defaults to UNIT test).
949
   * \param type The TestType of the test suite (defaults to UNIT test).
1060
   */
950
   */
1061
  TestSuite (std::string name, TestType type = UNIT);
951
  TestSuite (std::string name, Type type = UNIT);
1062
1063
  /**
1064
   * \brief Destroy a test suite.
1065
   */
1066
  virtual ~TestSuite ();
1067
1068
  /**
1069
   * \brief Run this test suite.
1070
   *
1071
   * \returns Boolean sense of "an error has occurred."
1072
   */
1073
  bool Run (void);
1074
1075
  /**
1076
   * \brief Add an individual test case to this test suite.
1077
   *
1078
   * \param testCase Pointer to the test case object to be added.
1079
   * \returns Integer assigned as identifer of the provided test case.
1080
   */
1081
  uint32_t AddTestCase (TestCase *testCase);
1082
1083
  /**
1084
   * \brief Get the number of test cases that have been added to this test suite.
1085
   *
1086
   * \returns Number of test cases in the suite.
1087
   */
1088
  uint32_t GetNTestCases (void);
1089
1090
  /**
1091
   * \brief Get the test case at index i.
1092
   */
1093
  TestCase *GetTestCase (uint32_t i);
1094
952
1095
  /**
953
  /**
1096
   * \brief get the kind of test this test suite implements
954
   * \brief get the kind of test this test suite implements
1097
   *
955
   *
1098
   * \returns the TestType of the suite.
956
   * \returns the Type of the suite.
1099
   */
957
   */
1100
  TestType GetTestType (void);
958
  TestSuite::Type GetTestType (void);
1101
959
1102
  /**
960
private:
1103
   * \brief Set the verbosity of this test suite.
1104
   * \param verbose Whether or not to turn on any output the
1105
   *                test case may provide.
1106
   */
1107
  void SetVerbose (bool verbose);
1108
1109
  /**
1110
   * \brief Tell the test suite and its test cases whether or not to continue
1111
   * testing if an error is detected.
1112
   *
1113
   * Typically, test suites depend on some number of test cases, which in turn
1114
   * depend on some number of individual tests.  Often, these tests build on 
1115
   * functionality that has been previously verified.  In this case, subsequent
1116
   * test failures may simply be alternate manifestations of previously detected
1117
   * errors.  Some developers may only be interested in seeing the first failure.
1118
   * Other developers may want to see all the information they can get, and want
1119
   * to see all failures.  This is a matter of individual preference, so we allow
1120
   * this behavior to be configured.
1121
   *
1122
   * \param continueOnFailure If true, continue running test cases after a 
1123
   *                          failure has been detected, otherwise stop on the 
1124
   *                          first error.
1125
   */
1126
  void SetContinueOnFailure (bool continueOnFailure);
1127
1128
  /**
1129
   * \brief Set the name of this test suite.
1130
   */
1131
  void SetName (std::string name);
1132
1133
  /**
1134
   * \brief Get the name of this test suite.
1135
   */
1136
  std::string GetName (void);
1137
1138
  /**
1139
   * \brief Set the base directory of the ns-3 distribution.
1140
   */
1141
  void SetBaseDir (std::string basedir);
1142
1143
  /**
1144
   * \brief Get the base directory of the ns-3 distribution.
1145
   */
1146
  std::string GetBaseDir (void);
1147
1148
  /**
1149
   * \brief Set the temporary file directory (where to write temporary files).
1150
   */
1151
  void SetTempDir (std::string dir);
1152
1153
  /**
1154
   * \brief Get the temporary file directory.
1155
   */
1156
  std::string GetTempDir (void);
1157
1158
  /**
1159
   * \brief Set the stream to which status and result messages will be written.
1160
   *
1161
   * We really don't want to have to pass an ofstream around to every function
1162
   * and we especially don't want to have to make our clients plumb an ofstream
1163
   * around so we need to save it.  Since file streams are not designed to be
1164
   * copied or assigned (what does it mean to have duplicate streams to a file) 
1165
   * we have to stash a pointer to the stream.
1166
   * \param ofs output file stream
1167
   */
1168
  void SetStream (std::ofstream *ofs);
1169
1170
  /**
1171
   * \brief Manually update the error status of this test suite.
1172
   *
1173
   * This does a logical OR of the error argument with the current error status.
1174
   * If the argument is false, it does nothing.  If the argument is true, it 
1175
   * sets the error status to "an error has occurred."
1176
   *
1177
   * \param error The status to use to update the test suite error status
1178
   */
1179
  void UpdateErrorStatus (bool error);
1180
1181
  /**
1182
   * \brief Manually set the error status of this test suite.
1183
   *
1184
   * This sets the current error status to the argument provided.  Can be used
1185
   * to reset any previous errors if the argument is false.
1186
   *
1187
   * \param error The status to use to set the test suite error status
1188
   */
1189
  void SetErrorStatus (bool error);
1190
1191
  /**
1192
   * \brief Get the error status of this test suite.
1193
   */
1194
  bool GetErrorStatus (void);
1195
1196
  /**
1197
   * \brief Should test suite continue running cases in the presence of errors?
1198
   * \returns True if the test suite should continue, false otherwise.
1199
   */
1200
  bool ContinueOnFailure (void);
1201
1202
  /**
1203
   * \brief Issue a test report than the test suite has started running.
1204
   */
1205
  void ReportStart (void);
1206
1207
  /**
1208
   * \brief Issue a test report than the test suite has declared success.
1209
   */
1210
  void ReportSuccess (void);
1211
1212
  /**
1213
   * \brief Issue a test report than the test suite has found an error.
1214
   */
1215
  void ReportFailure (void);
1216
1217
  /**
1218
   * \brief Issue a test report than the test suite has completed its run.
1219
   */
1220
  void ReportEnd (void);
1221
1222
protected:
1223
  /**
1224
   * \internal
1225
   * \brief Implementation of reporting method for the start of the test suite.
1226
   */
1227
  virtual void DoReportStart (void);
1228
1229
  /**
1230
   * \internal
1231
   * \brief Implementation of reporting method for success of the test suite.
1232
   */
1233
  virtual void DoReportSuccess (void);
1234
1235
  /**
1236
   * \internal
1237
   * \brief Implementation of reporting method for failure of the test suite.
1238
   */
1239
  virtual void DoReportFailure (void);
1240
1241
  /**
1242
   * \internal
1243
   * \brief Implementation of reporting method for the end of the test suite.
1244
   */
1245
  virtual void DoReportEnd (void);
1246
1247
  /**
1248
   * \internal
1249
   * \brief Implementation to do any local setup required for this test suite.
1250
   */
1251
  virtual void DoSetup (void);
1252
1253
  /**
1254
   * \internal
1255
   * \brief Implementation to actually run this test suite.
1256
   */
1257
  virtual void DoRun (void);
961
  virtual void DoRun (void);
1258
962
1259
  /**
1260
   * \internal
1261
   * \brief Implementation to do any local setup required for this test suite.
1262
   */
1263
  virtual void DoTeardown (void);
1264
963
1265
private:
964
  TestSuite::Type m_type;  
1266
  TestSuite (TestSuite& ts);
1267
  TestSuite& operator= (TestSuite& ts);
1268
1269
  SystemWallClockMs m_msClock;
1270
  std::string m_name;
1271
  bool m_verbose;
1272
  bool m_continueOnFailure;
1273
  std::string m_basedir;
1274
  std::string m_tempdir;
1275
  std::ofstream *m_ofs;
1276
  bool m_error;
1277
  TestType m_type;
1278
1279
  typedef std::vector<TestCase *> TestCaseVector_t;
1280
  TestCaseVector_t m_tests;
1281
};
965
};
1282
966
1283
/**
967
/**
 Lines 1286-1294    Link Here 
1286
class TestRunner
970
class TestRunner
1287
{
971
{
1288
public:
972
public:
1289
  static uint32_t AddTestSuite (TestSuite *testSuite);
973
  static int Run (int argc, char *argv[]);
1290
  static uint32_t GetNTestSuites (void);
1291
  static TestSuite *GetTestSuite (uint32_t n);
1292
};
974
};
1293
975
1294
/**
976
/**
 Lines 1313-1320    Link Here 
1313
  TestVectors& operator= (const TestVectors& tv);
995
  TestVectors& operator= (const TestVectors& tv);
1314
  bool operator== (const TestVectors& tv) const;
996
  bool operator== (const TestVectors& tv) const;
1315
997
1316
  typedef std::vector<T> TestVector_t;
998
  typedef std::vector<T> TestVector;
1317
  TestVector_t m_vectors;
999
  TestVector m_vectors;
1318
};
1000
};
1319
1001
1320
template <typename T>
1002
template <typename T>
(-)a/src/core/wscript (-3 / +7 lines)
 Lines 79-86    Link Here 
79
79
80
    conf.check(header_name='stdint.h', define_name='HAVE_STDINT_H')
80
    conf.check(header_name='stdint.h', define_name='HAVE_STDINT_H')
81
    conf.check(header_name='inttypes.h', define_name='HAVE_INTTYPES_H')
81
    conf.check(header_name='inttypes.h', define_name='HAVE_INTTYPES_H')
82
83
    conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H')
82
    conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H')
83
    conf.check(header_name='sys/types.h', define_name='HAVE_SYS_TYPES_H')
84
    conf.check(header_name='sys/stat.h', define_name='HAVE_SYS_STAT_H')
85
    conf.check(header_name='dirent.h', define_name='HAVE_DIRENT_H')
84
86
85
    if not conf.check(lib='rt', uselib='RT', define_name='HAVE_RT'):
87
    if not conf.check(lib='rt', uselib='RT', define_name='HAVE_RT'):
86
        conf.report_optional_feature("RealTime", "Real Time Simulator",
88
        conf.report_optional_feature("RealTime", "Real Time Simulator",
 Lines 144-153    Link Here 
144
        'model/names.cc',
146
        'model/names.cc',
145
        'model/vector.cc',
147
        'model/vector.cc',
146
        'model/fatal-impl.cc',
148
        'model/fatal-impl.cc',
149
        'model/system-path.cc',
147
        ]
150
        ]
148
151
149
    core_test = bld.create_ns3_module_test_library('core')
152
    core_test_source = [
150
    core_test.source = [
151
        'test/attribute-test-suite.cc',
153
        'test/attribute-test-suite.cc',
152
        'test/callback-test-suite.cc',
154
        'test/callback-test-suite.cc',
153
        'test/command-line-test-suite.cc',
155
        'test/command-line-test-suite.cc',
 Lines 166-171    Link Here 
166
        'test/type-traits-test-suite.cc',
168
        'test/type-traits-test-suite.cc',
167
        'test/watchdog-test-suite.cc',
169
        'test/watchdog-test-suite.cc',
168
        ]
170
        ]
171
    core_test = bld.create_ns3_module_test_library('core', core_test_source)
169
172
170
    headers = bld.new_task_gen('ns3header')
173
    headers = bld.new_task_gen('ns3header')
171
    headers.module = 'core'
174
    headers.module = 'core'
 Lines 235-240    Link Here 
235
        'model/vector.h',
238
        'model/vector.h',
236
        'model/default-deleter.h',
239
        'model/default-deleter.h',
237
        'model/fatal-impl.h',
240
        'model/fatal-impl.h',
241
        'model/system-path.h',
238
        ]
242
        ]
239
243
240
    if sys.platform == 'win32':
244
    if sys.platform == 'win32':
(-)a/src/dsdv/wscript (-2 / +3 lines)
 Lines 11-20    Link Here 
11
        'helper/dsdv-helper.cc',
11
        'helper/dsdv-helper.cc',
12
        ]
12
        ]
13
13
14
    module_test = bld.create_ns3_module_test_library('dsdv')
14
    module_test_source = [
15
    module_test.source = [
16
        'test/dsdv-testcase.cc',
15
        'test/dsdv-testcase.cc',
17
        ]
16
        ]
17
    module_test = bld.create_ns3_module_test_library('dsdv',
18
                                                     module_test_source)
18
19
19
    headers = bld.new_task_gen('ns3header')
20
    headers = bld.new_task_gen('ns3header')
20
    headers.module = 'dsdv'
21
    headers.module = 'dsdv'
(-)a/src/energy/wscript (-2 / +3 lines)
 Lines 18-29    Link Here 
18
        'helper/rv-battery-model-helper.cc',
18
        'helper/rv-battery-model-helper.cc',
19
        ]
19
        ]
20
20
21
    obj_test = bld.create_ns3_module_test_library('energy')
21
    obj_test_source = [
22
    obj_test.source = [
23
        'test/basic-energy-model-test.cc',
22
        'test/basic-energy-model-test.cc',
24
        'test/rv-battery-model-test.cc',
23
        'test/rv-battery-model-test.cc',
25
        'test/li-ion-energy-source-test.cc',
24
        'test/li-ion-energy-source-test.cc',
26
        ]
25
        ]
26
    obj_test = bld.create_ns3_module_test_library('energy',
27
                                                  obj_test_source)
27
28
28
    headers = bld.new_task_gen('ns3header')
29
    headers = bld.new_task_gen('ns3header')
29
    headers.module = 'energy'
30
    headers.module = 'energy'
(-)a/src/flow-monitor/wscript (-2 / +3 lines)
 Lines 12-21    Link Here 
12
        ]]
12
        ]]
13
    obj.source.append("helper/flow-monitor-helper.cc")
13
    obj.source.append("helper/flow-monitor-helper.cc")
14
14
15
    module_test = bld.create_ns3_module_test_library('flow-monitor')
15
    module_test_source = [
16
    module_test.source = [
17
        'test/histogram-test-suite.cc',
16
        'test/histogram-test-suite.cc',
18
        ]
17
        ]
18
    module_test = bld.create_ns3_module_test_library('flow-monitor',
19
                                                     module_test_source)
19
20
20
    headers = bld.new_task_gen('ns3header')
21
    headers = bld.new_task_gen('ns3header')
21
    headers.module = 'flow-monitor'
22
    headers.module = 'flow-monitor'
(-)a/src/internet/wscript (-2 / +3 lines)
 Lines 185-192    Link Here 
185
        'helper/ipv6-routing-helper.cc',
185
        'helper/ipv6-routing-helper.cc',
186
        ]
186
        ]
187
187
188
    internet_test = bld.create_ns3_module_test_library('internet')
188
    internet_test_source = [
189
    internet_test.source = [
190
        'test/global-route-manager-impl-test-suite.cc',
189
        'test/global-route-manager-impl-test-suite.cc',
191
        'test/ipv4-address-generator-test-suite.cc',
190
        'test/ipv4-address-generator-test-suite.cc',
192
        'test/ipv4-address-helper-test-suite.cc',
191
        'test/ipv4-address-helper-test-suite.cc',
 Lines 201-206    Link Here 
201
        'test/tcp-test.cc',
200
        'test/tcp-test.cc',
202
        'test/udp-test.cc',
201
        'test/udp-test.cc',
203
        ]
202
        ]
203
    internet_test = bld.create_ns3_module_test_library('internet',
204
                                                       internet_test_source)
204
205
205
    headers = bld.new_task_gen('ns3header')
206
    headers = bld.new_task_gen('ns3header')
206
    headers.module = 'internet'
207
    headers.module = 'internet'
(-)a/src/lte/wscript (-2 / +3 lines)
 Lines 39-51    Link Here 
39
        'helper/lte-helper.cc',
39
        'helper/lte-helper.cc',
40
        ]
40
        ]
41
41
42
    module_test = bld.create_ns3_module_test_library('lte')
42
    module_test_source = [
43
    module_test.source = [
44
        'test/lte-phy-test.cc',
43
        'test/lte-phy-test.cc',
45
        'test/lte-device-test.cc',
44
        'test/lte-device-test.cc',
46
        'test/lte-bearer-test.cc',
45
        'test/lte-bearer-test.cc',
47
        'test/lte-propagation-loss-model-test.cc',
46
        'test/lte-propagation-loss-model-test.cc',
48
        ]
47
        ]
48
    module_test = bld.create_ns3_module_test_library('lte',
49
                                                     module_test_source)
49
    
50
    
50
    headers = bld.new_task_gen('ns3header')
51
    headers = bld.new_task_gen('ns3header')
51
    headers.module = 'lte'
52
    headers.module = 'lte'
(-)a/src/mesh/test/dot11s/hwmp-proactive-regression.cc (-14 / +4 lines)
 Lines 32-44    Link Here 
32
#include "ns3/abort.h"
32
#include "ns3/abort.h"
33
#include "ns3/udp-echo-helper.h"
33
#include "ns3/udp-echo-helper.h"
34
#include "ns3/mobility-model.h"
34
#include "ns3/mobility-model.h"
35
#include "ns3/pcap-test.h"
35
#include <sstream>
36
#include <sstream>
36
#include "hwmp-proactive-regression.h"
37
#include "hwmp-proactive-regression.h"
37
38
38
using namespace ns3;
39
using namespace ns3;
39
40
40
/// Set to true to rewrite reference traces, leave false to run regression test
41
const bool WRITE_VECTORS = false;
42
/// Unique PCAP file name prefix
41
/// Unique PCAP file name prefix
43
const char * const PREFIX = "hwmp-proactive-regression-test";
42
const char * const PREFIX = "hwmp-proactive-regression-test";
44
43
 Lines 65-71    Link Here 
65
  Simulator::Run ();
64
  Simulator::Run ();
66
  Simulator::Destroy ();
65
  Simulator::Destroy ();
67
66
68
  if (!WRITE_VECTORS) CheckResults ();
67
  CheckResults ();
69
68
70
  delete m_nodes, m_nodes = 0;
69
  delete m_nodes, m_nodes = 0;
71
}
70
}
 Lines 122-129    Link Here 
122
  address.SetBase ("10.1.1.0", "255.255.255.0");
121
  address.SetBase ("10.1.1.0", "255.255.255.0");
123
  m_interfaces = address.Assign (meshDevices);
122
  m_interfaces = address.Assign (meshDevices);
124
  // 4. write PCAP if needed
123
  // 4. write PCAP if needed
125
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : std::string (GetTempDir ())) + PREFIX;
124
  wifiPhy.EnablePcapAll (CreateTempDirFilename (PREFIX));
126
  wifiPhy.EnablePcapAll (prefix);
127
}
125
}
128
126
129
void
127
void
 Lines 131-145    Link Here 
131
{
129
{
132
  for (int i = 0; i < 5; ++i)
130
  for (int i = 0; i < 5; ++i)
133
    {
131
    {
134
      std::ostringstream os1, os2;
132
      NS_PCAP_TEST_EXPECT_EQ (PREFIX << "-" << i << "-1.pcap");
135
      // File naming conventions are hard-coded here.
136
      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-1.pcap";
137
      os2 << GetTempDir () << PREFIX << "-" << i << "-1.pcap";
138
139
      uint32_t sec (0), usec (0);
140
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec); // TODO support default PcapWriter snap length here
141
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
142
                                                         << " differ starting from " << sec << " s " << usec << " us");
143
    }
133
    }
144
}
134
}
145
135
(-)a/src/mesh/test/dot11s/hwmp-reactive-regression.cc (-15 / +4 lines)
 Lines 31-42    Link Here 
31
#include "ns3/abort.h"
31
#include "ns3/abort.h"
32
#include "ns3/udp-echo-helper.h"
32
#include "ns3/udp-echo-helper.h"
33
#include "ns3/mobility-model.h"
33
#include "ns3/mobility-model.h"
34
#include "ns3/pcap-test.h"
34
#include <sstream>
35
#include <sstream>
35
36
36
#include "hwmp-reactive-regression.h"
37
#include "hwmp-reactive-regression.h"
37
38
38
/// Set to true to rewrite reference traces, leave false to run regression test
39
const bool WRITE_VECTORS = false;
40
/// Unique PCAP file name prefix
39
/// Unique PCAP file name prefix
41
const char * const PREFIX = "hwmp-reactive-regression-test";
40
const char * const PREFIX = "hwmp-reactive-regression-test";
42
41
 Lines 61-67    Link Here 
61
  Simulator::Run ();
60
  Simulator::Run ();
62
  Simulator::Destroy ();
61
  Simulator::Destroy ();
63
62
64
  if (!WRITE_VECTORS) CheckResults ();
63
  CheckResults ();
65
  delete m_nodes, m_nodes = 0;
64
  delete m_nodes, m_nodes = 0;
66
}
65
}
67
void
66
void
 Lines 119-127    Link Here 
119
  address.SetBase ("10.1.1.0", "255.255.255.0");
118
  address.SetBase ("10.1.1.0", "255.255.255.0");
120
  m_interfaces = address.Assign (meshDevices);
119
  m_interfaces = address.Assign (meshDevices);
121
  // 4. write PCAP if needed
120
  // 4. write PCAP if needed
122
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : std::string (GetTempDir ())) + PREFIX;
121
  wifiPhy.EnablePcapAll (CreateTempDirFilename (PREFIX));
123
  wifiPhy.EnablePcapAll (prefix);
124
125
}
122
}
126
123
127
void
124
void
 Lines 129-143    Link Here 
129
{
126
{
130
  for (int i = 0; i < 6; ++i)
127
  for (int i = 0; i < 6; ++i)
131
    {
128
    {
132
      std::ostringstream os1, os2;
129
      NS_PCAP_TEST_EXPECT_EQ (PREFIX << "-" << i << "-1.pcap");
133
      // File naming conventions are hard-coded here.
134
      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-1.pcap";
135
      os2 << GetTempDir () << PREFIX << "-" << i << "-1.pcap";
136
137
      uint32_t sec (0), usec (0);
138
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec); // TODO support default PcapWriter snap length here
139
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
140
                                                         << " differ starting from " << sec << " s " << usec << " us");
141
    }
130
    }
142
}
131
}
143
132
(-)a/src/mesh/test/dot11s/hwmp-simplest-regression.cc (-14 / +4 lines)
 Lines 31-43    Link Here 
31
#include "ns3/abort.h"
31
#include "ns3/abort.h"
32
#include "ns3/udp-echo-helper.h"
32
#include "ns3/udp-echo-helper.h"
33
#include "ns3/mobility-model.h"
33
#include "ns3/mobility-model.h"
34
#include "ns3/pcap-test.h"
34
#include <sstream>
35
#include <sstream>
35
#include "hwmp-simplest-regression.h"
36
#include "hwmp-simplest-regression.h"
36
37
37
using namespace ns3;
38
using namespace ns3;
38
39
39
/// Set to true to rewrite reference traces, leave false to run regression test
40
const bool WRITE_VECTORS = false;
41
/// Unique PCAP file name prefix
40
/// Unique PCAP file name prefix
42
const char * const PREFIX = "hwmp-simplest-regression-test";
41
const char * const PREFIX = "hwmp-simplest-regression-test";
43
42
 Lines 64-70    Link Here 
64
  Simulator::Run ();
63
  Simulator::Run ();
65
  Simulator::Destroy ();
64
  Simulator::Destroy ();
66
65
67
  if (!WRITE_VECTORS) CheckResults ();
66
  CheckResults ();
68
67
69
  delete m_nodes, m_nodes = 0;
68
  delete m_nodes, m_nodes = 0;
70
}
69
}
 Lines 131-138    Link Here 
131
  address.SetBase ("10.1.1.0", "255.255.255.0");
130
  address.SetBase ("10.1.1.0", "255.255.255.0");
132
  m_interfaces = address.Assign (meshDevices);
131
  m_interfaces = address.Assign (meshDevices);
133
  // 4. write PCAP if needed
132
  // 4. write PCAP if needed
134
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : std::string (GetTempDir ())) + PREFIX;
133
  wifiPhy.EnablePcapAll (CreateTempDirFilename (PREFIX));
135
  wifiPhy.EnablePcapAll (prefix);
136
}
134
}
137
135
138
void
136
void
 Lines 140-154    Link Here 
140
{
138
{
141
  for (int i = 0; i < 2; ++i)
139
  for (int i = 0; i < 2; ++i)
142
    {
140
    {
143
      std::ostringstream os1, os2;
141
      NS_PCAP_TEST_EXPECT_EQ (PREFIX << "-" << i << "-1.pcap");
144
      // File naming conventions are hard-coded here.
145
      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-1.pcap";
146
      os2 << GetTempDir () << PREFIX << "-" << i << "-1.pcap";
147
148
      uint32_t sec (0), usec (0);
149
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec); // TODO support default PcapWriter snap length here
150
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
151
                                                         << " differ starting from " << sec << " s " << usec << " us");
152
    }
142
    }
153
}
143
}
154
144
(-)a/src/mesh/test/dot11s/hwmp-target-flags-regression.cc (-14 / +4 lines)
 Lines 31-43    Link Here 
31
#include "ns3/abort.h"
31
#include "ns3/abort.h"
32
#include "ns3/udp-echo-helper.h"
32
#include "ns3/udp-echo-helper.h"
33
#include "ns3/mobility-model.h"
33
#include "ns3/mobility-model.h"
34
#include "ns3/pcap-test.h"
34
#include <sstream>
35
#include <sstream>
35
#include "hwmp-target-flags-regression.h"
36
#include "hwmp-target-flags-regression.h"
36
37
37
using namespace ns3;
38
using namespace ns3;
38
39
39
/// Set to true to rewrite reference traces, leave false to run regression test
40
const bool WRITE_VECTORS = false;
41
/// Unique PCAP file name prefix
40
/// Unique PCAP file name prefix
42
const char * const PREFIX = "hwmp-target-flags-regression-test";
41
const char * const PREFIX = "hwmp-target-flags-regression-test";
43
42
 Lines 64-70    Link Here 
64
  Simulator::Run ();
63
  Simulator::Run ();
65
  Simulator::Destroy ();
64
  Simulator::Destroy ();
66
65
67
  if (!WRITE_VECTORS) CheckResults ();
66
  CheckResults ();
68
67
69
  delete m_nodes, m_nodes = 0;
68
  delete m_nodes, m_nodes = 0;
70
}
69
}
 Lines 138-145    Link Here 
138
  address.SetBase ("10.1.1.0", "255.255.255.0");
137
  address.SetBase ("10.1.1.0", "255.255.255.0");
139
  m_interfaces = address.Assign (meshDevices);
138
  m_interfaces = address.Assign (meshDevices);
140
  // 4. write PCAP if needed
139
  // 4. write PCAP if needed
141
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : std::string (GetTempDir ())) + PREFIX;
140
  wifiPhy.EnablePcapAll (CreateTempDirFilename (PREFIX));
142
  wifiPhy.EnablePcapAll (prefix);
143
}
141
}
144
142
145
void
143
void
 Lines 147-161    Link Here 
147
{
145
{
148
  for (int i = 0; i < 4; ++i)
146
  for (int i = 0; i < 4; ++i)
149
    {
147
    {
150
      std::ostringstream os1, os2;
148
      NS_PCAP_TEST_EXPECT_EQ (PREFIX << "-" << i << "-1.pcap");
151
      // File naming conventions are hard-coded here.
152
      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-1.pcap";
153
      os2 << GetTempDir () << PREFIX << "-" << i << "-1.pcap";
154
155
      uint32_t sec (0), usec (0);
156
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec); // TODO support default PcapWriter snap length here
157
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
158
                                                         << " differ starting from " << sec << " s " << usec << " us");
159
    }
149
    }
160
}
150
}
161
151
(-)a/src/mesh/test/dot11s/pmp-regression.cc (-14 / +4 lines)
 Lines 28-41    Link Here 
28
#include "ns3/internet-stack-helper.h"
28
#include "ns3/internet-stack-helper.h"
29
#include "ns3/mobility-model.h"
29
#include "ns3/mobility-model.h"
30
#include "ns3/pcap-file.h"
30
#include "ns3/pcap-file.h"
31
#include "ns3/pcap-test.h"
31
#include <sstream>
32
#include <sstream>
32
33
33
#include "pmp-regression.h"
34
#include "pmp-regression.h"
34
35
35
using namespace ns3;
36
using namespace ns3;
36
37
37
/// Set to true to rewrite reference traces, leave false to run regression test
38
const bool WRITE_VECTORS = false;
39
/// Unique PCAP file name prefix
38
/// Unique PCAP file name prefix
40
const char * const PREFIX = "pmp-regression-test";
39
const char * const PREFIX = "pmp-regression-test";
41
40
 Lines 61-67    Link Here 
61
  Simulator::Run ();
60
  Simulator::Run ();
62
  Simulator::Destroy ();
61
  Simulator::Destroy ();
63
62
64
  if (!WRITE_VECTORS) CheckResults ();
63
  CheckResults ();
65
64
66
  delete m_nodes, m_nodes = 0;
65
  delete m_nodes, m_nodes = 0;
67
}
66
}
 Lines 97-104    Link Here 
97
  mesh.SetNumberOfInterfaces (1);
96
  mesh.SetNumberOfInterfaces (1);
98
  NetDeviceContainer meshDevices = mesh.Install (wifiPhy, *m_nodes);
97
  NetDeviceContainer meshDevices = mesh.Install (wifiPhy, *m_nodes);
99
  // 3. write PCAP if needed
98
  // 3. write PCAP if needed
100
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : std::string (GetTempDir ())) + PREFIX;
99
  wifiPhy.EnablePcapAll (CreateTempDirFilename (PREFIX));
101
  wifiPhy.EnablePcapAll (prefix);
102
}
100
}
103
101
104
void
102
void
 Lines 106-120    Link Here 
106
{
104
{
107
  for (int i = 0; i < 2; ++i)
105
  for (int i = 0; i < 2; ++i)
108
    {
106
    {
109
      std::ostringstream os1, os2;
107
      NS_PCAP_TEST_EXPECT_EQ (PREFIX << "-" << i << "-1.pcap");
110
      // File naming conventions are hard-coded here.
111
      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-1.pcap";
112
      os2 << GetTempDir () << PREFIX << "-" << i << "-1.pcap";
113
114
      uint32_t sec (0), usec (0);
115
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec); // TODO support default PcapWriter snap length here
116
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
117
                                                         << " differ starting from " << sec << " s " << usec << " us");
118
    }
108
    }
119
}
109
}
120
110
(-)a/src/mesh/test/dot11s/regression.cc (+1 lines)
 Lines 31-36    Link Here 
31
public:
31
public:
32
  Dot11sRegressionSuite () : TestSuite ("devices-mesh-dot11s-regression", SYSTEM) 
32
  Dot11sRegressionSuite () : TestSuite ("devices-mesh-dot11s-regression", SYSTEM) 
33
  {
33
  {
34
    SetDataDir (NS_TEST_SOURCEDIR);
34
    AddTestCase (new PeerManagementProtocolRegressionTest);
35
    AddTestCase (new PeerManagementProtocolRegressionTest);
35
    AddTestCase (new HwmpSimplestRegressionTest);
36
    AddTestCase (new HwmpSimplestRegressionTest);
36
    AddTestCase (new HwmpReactiveRegressionTest);
37
    AddTestCase (new HwmpReactiveRegressionTest);
(-)a/src/mesh/test/flame/flame-regression.cc (-14 / +4 lines)
 Lines 28-33    Link Here 
28
#include "ns3/internet-stack-helper.h"
28
#include "ns3/internet-stack-helper.h"
29
#include "ns3/ipv4-address-helper.h"
29
#include "ns3/ipv4-address-helper.h"
30
#include "ns3/abort.h"
30
#include "ns3/abort.h"
31
#include "ns3/pcap-test.h"
31
#include "ns3/udp-echo-helper.h"
32
#include "ns3/udp-echo-helper.h"
32
#include "ns3/mobility-model.h"
33
#include "ns3/mobility-model.h"
33
#include <sstream>
34
#include <sstream>
 Lines 36-43    Link Here 
36
37
37
using namespace ns3;
38
using namespace ns3;
38
39
39
/// Set to true to rewrite reference traces, leave false to run regression test
40
const bool WRITE_VECTORS = false;
41
/// Unique PCAP file name prefix
40
/// Unique PCAP file name prefix
42
const char * const PREFIX = "flame-regression-test";
41
const char * const PREFIX = "flame-regression-test";
43
42
 Lines 65-71    Link Here 
65
  Simulator::Run ();
64
  Simulator::Run ();
66
  Simulator::Destroy ();
65
  Simulator::Destroy ();
67
66
68
  if (!WRITE_VECTORS) CheckResults ();
67
  CheckResults ();
69
68
70
  delete m_nodes, m_nodes = 0;
69
  delete m_nodes, m_nodes = 0;
71
}
70
}
 Lines 109-116    Link Here 
109
  address.SetBase ("10.1.1.0", "255.255.255.0");
108
  address.SetBase ("10.1.1.0", "255.255.255.0");
110
  m_interfaces = address.Assign (meshDevices);
109
  m_interfaces = address.Assign (meshDevices);
111
  // 4. write PCAP if needed
110
  // 4. write PCAP if needed
112
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : GetTempDir ()) + PREFIX;
111
  wifiPhy.EnablePcapAll (CreateTempDirFilename (PREFIX));
113
  wifiPhy.EnablePcapAll (prefix);
114
112
115
}
113
}
116
void
114
void
 Lines 134-148    Link Here 
134
{
132
{
135
  for (int i = 0; i < 3; ++i)
133
  for (int i = 0; i < 3; ++i)
136
    {
134
    {
137
      std::ostringstream os1, os2;
135
      NS_PCAP_TEST_EXPECT_EQ (PREFIX << "-" << i << "-1.pcap");
138
      // File naming conventions are hard-coded here.
139
      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-1.pcap";
140
      os2 << GetTempDir () << PREFIX << "-" << i << "-1.pcap";
141
142
      uint32_t sec (0), usec (0);
143
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec); // TODO support default PcapWriter snap length here
144
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
145
                                                         << " differ starting from " << sec << " s " << usec << " us");
146
    }
136
    }
147
}
137
}
148
138
(-)a/src/mesh/test/flame/flame-test-suite.cc (-1 / +1 lines)
 Lines 87-93    Link Here 
87
static FlameRtableTest g_FlameRtableTest;
87
static FlameRtableTest g_FlameRtableTest;
88
88
89
FlameRtableTest::FlameRtableTest () :
89
FlameRtableTest::FlameRtableTest () :
90
  TestCase ("Mesh/Flame/FlameRtable"), 
90
  TestCase ("FlameRtable"), 
91
  error (false), 
91
  error (false), 
92
  dst ("01:00:00:01:00:01"), 
92
  dst ("01:00:00:01:00:01"), 
93
  hop ("01:00:00:01:00:03"),
93
  hop ("01:00:00:01:00:03"),
(-)a/src/mesh/test/flame/regression.cc (+1 lines)
 Lines 27-32    Link Here 
27
public:
27
public:
28
  FlameRegressionSuite () : TestSuite ("devices-mesh-flame-regression", SYSTEM) 
28
  FlameRegressionSuite () : TestSuite ("devices-mesh-flame-regression", SYSTEM) 
29
  {
29
  {
30
    SetDataDir (NS_TEST_SOURCEDIR);
30
    AddTestCase (new FlameRegressionTest);
31
    AddTestCase (new FlameRegressionTest);
31
  }
32
  }
32
} g_flameRegressionSuite;
33
} g_flameRegressionSuite;
(-)a/src/mesh/wscript (-2 / +2 lines)
 Lines 38-45    Link Here 
38
        'helper/flame/flame-installer.cc',
38
        'helper/flame/flame-installer.cc',
39
        ]
39
        ]
40
40
41
    obj_test = bld.create_ns3_module_test_library('mesh')
41
    obj_test_source = [
42
    obj_test.source = [
43
        'test/mesh-information-element-vector-test-suite.cc',
42
        'test/mesh-information-element-vector-test-suite.cc',
44
        'test/dot11s/dot11s-test-suite.cc',
43
        'test/dot11s/dot11s-test-suite.cc',
45
        'test/dot11s/pmp-regression.cc',
44
        'test/dot11s/pmp-regression.cc',
 Lines 52-57    Link Here 
52
        'test/flame/flame-regression.cc',
51
        'test/flame/flame-regression.cc',
53
        'test/flame/regression.cc',
52
        'test/flame/regression.cc',
54
        ]
53
        ]
54
    obj_test = bld.create_ns3_module_test_library('mesh', obj_test_source)
55
55
56
    headers = bld.new_task_gen('ns3header')
56
    headers = bld.new_task_gen('ns3header')
57
    headers.module = 'mesh'
57
    headers.module = 'mesh'
(-)a/src/mobility/test/ns2-mobility-helper-test-suite.cc (-2 / +4 lines)
 Lines 140-146    Link Here 
140
  /// Dump NS-2 trace to tmp file
140
  /// Dump NS-2 trace to tmp file
141
  bool WriteTrace ()
141
  bool WriteTrace ()
142
  {
142
  {
143
    m_traceFile = GetTempDir () + "Ns2MobilityHelperTest.tcl";
143
    m_traceFile = CreateTempDirFilename ("Ns2MobilityHelperTest.tcl");
144
    std::ofstream of (m_traceFile.c_str ());
144
    std::ofstream of (m_traceFile.c_str ());
145
    NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL (of.is_open (), true, "Need to write tmp. file");
145
    NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL (of.is_open (), true, "Need to write tmp. file");
146
    of << m_trace;
146
    of << m_trace;
 Lines 176-182    Link Here 
176
176
177
        m_nextRefPoint++;
177
        m_nextRefPoint++;
178
      }
178
      }
179
    return GetErrorStatus ();
179
    return IsStatusFailure ();
180
  }
180
  }
181
  /// Listen for course change events
181
  /// Listen for course change events
182
  void CourseChange (std::string context, Ptr<const MobilityModel> mobility)
182
  void CourseChange (std::string context, Ptr<const MobilityModel> mobility)
 Lines 243-248    Link Here 
243
public:
243
public:
244
  Ns2MobilityHelperTestSuite () : TestSuite ("mobility-ns2-trace-helper", UNIT)
244
  Ns2MobilityHelperTestSuite () : TestSuite ("mobility-ns2-trace-helper", UNIT)
245
  {
245
  {
246
    SetDataDir (NS_TEST_SOURCEDIR);
247
246
    // to be used as temporary variable for test cases.
248
    // to be used as temporary variable for test cases.
247
    // Note that test suite takes care of deleting all test cases.
249
    // Note that test suite takes care of deleting all test cases.
248
    Ns2MobilityHelperTest * t (0);
250
    Ns2MobilityHelperTest * t (0);
(-)a/src/mobility/wscript (-2 / +3 lines)
 Lines 23-34    Link Here 
23
        'helper/ns2-mobility-helper.cc',
23
        'helper/ns2-mobility-helper.cc',
24
        ]
24
        ]
25
25
26
    mobility_test = bld.create_ns3_module_test_library('mobility')
26
    mobility_test_source = [
27
    mobility_test.source = [
28
        'test/ns2-mobility-helper-test-suite.cc',
27
        'test/ns2-mobility-helper-test-suite.cc',
29
        'test/steady-state-random-waypoint-mobility-model-test.cc',
28
        'test/steady-state-random-waypoint-mobility-model-test.cc',
30
        'test/waypoint-mobility-model-test.cc',
29
        'test/waypoint-mobility-model-test.cc',
31
        ]
30
        ]
31
    mobility_test = bld.create_ns3_module_test_library('mobility',
32
                                                       mobility_test_source)
32
33
33
    headers = bld.new_task_gen('ns3header')
34
    headers = bld.new_task_gen('ns3header')
34
    headers.module = 'mobility'
35
    headers.module = 'mobility'
(-)a/src/network/model/buffer.cc (-4 / +5 lines)
 Lines 758-766    Link Here 
758
      uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
758
      uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
759
      memcpy (buffer, (const char*)(m_data->m_data + m_start), tmpsize);
759
      memcpy (buffer, (const char*)(m_data->m_data + m_start), tmpsize);
760
      buffer += tmpsize;
760
      buffer += tmpsize;
761
      if (size > tmpsize) 
761
      size -= tmpsize;
762
      if (size > 0) 
762
        { 
763
        { 
763
          size -= m_zeroAreaStart-m_start;
764
          tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
764
          tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
765
          uint32_t left = tmpsize;
765
          uint32_t left = tmpsize;
766
          while (left > 0)
766
          while (left > 0)
 Lines 770-780    Link Here 
770
              left -= toWrite;
770
              left -= toWrite;
771
              buffer += toWrite;
771
              buffer += toWrite;
772
            }
772
            }
773
          if (size > tmpsize)
773
          size -= tmpsize;
774
          if (size > 0)
774
            {
775
            {
775
              size -= tmpsize;
776
              tmpsize = std::min (m_end - m_zeroAreaEnd, size);
776
              tmpsize = std::min (m_end - m_zeroAreaEnd, size);
777
              memcpy (buffer, (const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
777
              memcpy (buffer, (const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
778
              size -= tmpsize;
778
            }
779
            }
779
        }
780
        }
780
    }
781
    }
(-)a/src/network/test/packetbb-test-suite.cc (-18 / +12 lines)
 Lines 40-47    Link Here 
40
  virtual void DoRun (void);
40
  virtual void DoRun (void);
41
41
42
private:
42
private:
43
  bool TestSerialize (void);
43
  void TestSerialize (void);
44
  bool TestDeserialize (void);
44
  void TestDeserialize (void);
45
45
46
  Ptr<PbbPacket> m_refPacket;
46
  Ptr<PbbPacket> m_refPacket;
47
  Buffer m_refBuffer;
47
  Buffer m_refBuffer;
 Lines 65-108    Link Here 
65
void
65
void
66
PbbTestCase::DoRun (void)
66
PbbTestCase::DoRun (void)
67
{
67
{
68
  NS_TEST_ASSERT_MSG_EQ (TestSerialize (), false,
68
  TestSerialize ();
69
                         "serialization failed");
69
  TestDeserialize ();
70
  NS_TEST_ASSERT_MSG_EQ (TestDeserialize (), false,
71
                         "deserialization failed");
72
}
70
}
73
71
74
bool
72
void
75
PbbTestCase::TestSerialize (void)
73
PbbTestCase::TestSerialize (void)
76
{
74
{
77
  Buffer newBuffer;
75
  Buffer newBuffer;
78
  newBuffer.AddAtStart (m_refPacket->GetSerializedSize ());
76
  newBuffer.AddAtStart (m_refPacket->GetSerializedSize ());
79
  m_refPacket->Serialize (newBuffer.Begin ());
77
  m_refPacket->Serialize (newBuffer.Begin ());
80
78
81
  NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL (newBuffer.GetSize (), m_refBuffer.GetSize (),
79
  NS_TEST_ASSERT_MSG_EQ (newBuffer.GetSize (), m_refBuffer.GetSize (),
82
                                      "serialization failed, buffers have different sizes");
80
                         "serialization failed, buffers have different sizes");
83
81
84
  int memrv = memcmp (newBuffer.PeekData (), m_refBuffer.PeekData (),
82
  int memrv = memcmp (newBuffer.PeekData (), m_refBuffer.PeekData (),
85
                      newBuffer.GetSize ());
83
                      newBuffer.GetSize ());
86
84
87
  NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL (memrv, 0,
85
  NS_TEST_ASSERT_MSG_EQ (memrv, 0,
88
                                      "serialization faled, buffers differ");
86
                         "serialization faled, buffers differ");
89
90
  return GetErrorStatus ();
91
}
87
}
92
88
93
bool
89
void
94
PbbTestCase::TestDeserialize (void)
90
PbbTestCase::TestDeserialize (void)
95
{
91
{
96
  Ptr<PbbPacket> newPacket = Create<PbbPacket> ();
92
  Ptr<PbbPacket> newPacket = Create<PbbPacket> ();
97
  uint32_t numbytes = newPacket->Deserialize (m_refBuffer.Begin ());
93
  uint32_t numbytes = newPacket->Deserialize (m_refBuffer.Begin ());
98
94
99
  NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL (numbytes, m_refBuffer.GetSize (),
95
  NS_TEST_ASSERT_MSG_EQ (numbytes, m_refBuffer.GetSize (),
100
                                      "deserialization failed, did not use all bytes");
96
                                      "deserialization failed, did not use all bytes");
101
97
102
  NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL (*newPacket, *m_refPacket,
98
  NS_TEST_ASSERT_MSG_EQ (*newPacket, *m_refPacket,
103
                                      "deserialization failed, objects do not match");
99
                                      "deserialization failed, objects do not match");
104
105
  return GetErrorStatus ();
106
}
100
}
107
101
108
class PbbTestSuite : public TestSuite
102
class PbbTestSuite : public TestSuite
(-)a/src/network/test/pcap-file-test-suite.cc (-7 / +8 lines)
 Lines 107-113    Link Here 
107
  std::stringstream filename;
107
  std::stringstream filename;
108
  uint32_t n = rand ();
108
  uint32_t n = rand ();
109
  filename << n;
109
  filename << n;
110
  m_testFilename = GetTempDir () + filename.str () + ".pcap";
110
  m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
111
}
111
}
112
112
113
void
113
void
 Lines 219-225    Link Here 
219
  std::stringstream filename;
219
  std::stringstream filename;
220
  uint32_t n = rand ();
220
  uint32_t n = rand ();
221
  filename << n;
221
  filename << n;
222
  m_testFilename = GetTempDir () + filename.str () + ".pcap";
222
  m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
223
}
223
}
224
224
225
void
225
void
 Lines 325-331    Link Here 
325
  std::stringstream filename;
325
  std::stringstream filename;
326
  uint32_t n = rand ();
326
  uint32_t n = rand ();
327
  filename << n;
327
  filename << n;
328
  m_testFilename = GetTempDir () + filename.str () + ".pcap";
328
  m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
329
}
329
}
330
330
331
void
331
void
 Lines 431-437    Link Here 
431
  std::stringstream filename;
431
  std::stringstream filename;
432
  uint32_t n = rand ();
432
  uint32_t n = rand ();
433
  filename << n;
433
  filename << n;
434
  m_testFilename = GetTempDir () + filename.str () + ".pcap";
434
  m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
435
}
435
}
436
436
437
void
437
void
 Lines 668-674    Link Here 
668
  std::stringstream filename;
668
  std::stringstream filename;
669
  uint32_t n = rand ();
669
  uint32_t n = rand ();
670
  filename << n;
670
  filename << n;
671
  m_testFilename = GetTempDir () + filename.str () + ".pcap";
671
  m_testFilename = CreateTempDirFilename (filename.str () + ".pcap");
672
}
672
}
673
673
674
void
674
void
 Lines 1008-1014    Link Here 
1008
1008
1009
  //
1009
  //
1010
  //
1010
  //
1011
  std::string filename = NS_TEST_SOURCEDIR + "known.pcap";
1011
  std::string filename = CreateDataDirFilename ("known.pcap");
1012
  f.Open (filename, std::ios::in);
1012
  f.Open (filename, std::ios::in);
1013
  NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << filename << 
1013
  NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << filename << 
1014
                         ", \"std::ios::in\") returns error");
1014
                         ", \"std::ios::in\") returns error");
 Lines 1070-1076    Link Here 
1070
  //
1070
  //
1071
  // Check that PcapDiff(file, file) is false
1071
  // Check that PcapDiff(file, file) is false
1072
  //
1072
  //
1073
  std::string filename = NS_TEST_SOURCEDIR + "known.pcap";
1073
  std::string filename = CreateDataDirFilename ("known.pcap");
1074
  uint32_t sec (0), usec (0);
1074
  uint32_t sec (0), usec (0);
1075
  bool diff = PcapFile::Diff (filename, filename, sec, usec);
1075
  bool diff = PcapFile::Diff (filename, filename, sec, usec);
1076
  NS_TEST_EXPECT_MSG_EQ (diff, false, "PcapDiff(file, file) must always be false");
1076
  NS_TEST_EXPECT_MSG_EQ (diff, false, "PcapDiff(file, file) must always be false");
 Lines 1110-1115    Link Here 
1110
PcapFileTestSuite::PcapFileTestSuite ()
1110
PcapFileTestSuite::PcapFileTestSuite ()
1111
  : TestSuite ("pcap-file", UNIT)
1111
  : TestSuite ("pcap-file", UNIT)
1112
{
1112
{
1113
  SetDataDir (NS_TEST_SOURCEDIR);
1113
  AddTestCase (new WriteModeCreateTestCase);
1114
  AddTestCase (new WriteModeCreateTestCase);
1114
  AddTestCase (new ReadModeCreateTestCase);
1115
  AddTestCase (new ReadModeCreateTestCase);
1115
  //AddTestCase (new AppendModeCreateTestCase);
1116
  //AddTestCase (new AppendModeCreateTestCase);
(-)3c68eb316f5f (+34 lines)
Added Link Here 
1
#ifndef PCAP_TEST_H
2
#define PCAP_TEST_H
3
4
#include <sstream>
5
#include <string>
6
#include <stdint.h>
7
#include "pcap-file.h"
8
#include "ns3/test.h"
9
10
/**
11
 * \brief Test that a pair of reference/new pcap files are equal
12
 *
13
 * The filename is interpreted as a stream.
14
 *
15
 * \param filename The name of the file to read in the reference/temporary
16
 *        directories
17
 */
18
#define NS_PCAP_TEST_EXPECT_EQ(filename)                                \
19
  do {                                                                  \
20
    std::ostringstream oss;                                             \
21
    oss << filename;                                                    \
22
    std::string expected = CreateDataDirFilename (oss.str());           \
23
    std::string got = CreateTempDirFilename (oss.str());                \
24
    uint32_t sec(0), usec(0);                                           \
25
    /* TODO support default PcapWriter snap length here */              \
26
    bool diff = PcapFile::Diff (got, expected, sec, usec);              \
27
    NS_TEST_EXPECT_MSG_EQ (diff, false,                                 \
28
                           "PCAP traces " << got << " and " << expected \
29
                           << " differ starting from " << sec << " s "  \
30
                           << usec << " us");                           \
31
  } while (false)
32
33
34
#endif /* PCAP_TEST_H */
(-)a/src/network/wscript (-2 / +4 lines)
 Lines 56-63    Link Here 
56
        'helper/trace-helper.cc',
56
        'helper/trace-helper.cc',
57
        ]
57
        ]
58
58
59
    network_test = bld.create_ns3_module_test_library('network')
59
    network_test_source = [
60
    network_test.source = [
61
        'test/buffer-test.cc',
60
        'test/buffer-test.cc',
62
        'test/drop-tail-queue-test-suite.cc',
61
        'test/drop-tail-queue-test-suite.cc',
63
        'test/packetbb-test-suite.cc',
62
        'test/packetbb-test-suite.cc',
 Lines 66-71    Link Here 
66
        'test/pcap-file-test-suite.cc',
65
        'test/pcap-file-test-suite.cc',
67
        'test/sequence-number-test-suite.cc',
66
        'test/sequence-number-test-suite.cc',
68
        ]
67
        ]
68
    network_test = bld.create_ns3_module_test_library('network',
69
                                                      network_test_source)
69
70
70
    headers = bld.new_task_gen('ns3header')
71
    headers = bld.new_task_gen('ns3header')
71
    headers.module = 'network'
72
    headers.module = 'network'
 Lines 119-124    Link Here 
119
        'utils/sgi-hashmap.h',
120
        'utils/sgi-hashmap.h',
120
        'utils/simple-channel.h',
121
        'utils/simple-channel.h',
121
        'utils/simple-net-device.h',
122
        'utils/simple-net-device.h',
123
        'utils/pcap-test.h',
122
        'helper/application-container.h',
124
        'helper/application-container.h',
123
        'helper/net-device-container.h',
125
        'helper/net-device-container.h',
124
        'helper/node-container.h',
126
        'helper/node-container.h',
(-)a/src/olsr/test/bug780-test.cc (-22 / +4 lines)
 Lines 38-53    Link Here 
38
#include "ns3/internet-stack-helper.h"
38
#include "ns3/internet-stack-helper.h"
39
#include "ns3/v4ping-helper.h"
39
#include "ns3/v4ping-helper.h"
40
#include "ns3/pcap-file.h"
40
#include "ns3/pcap-file.h"
41
#include "ns3/pcap-test.h"
41
42
42
#include "bug780-test.h"
43
#include "bug780-test.h"
43
44
44
/// Set to true to rewrite reference traces, leave false to run regression tests
45
namespace 
46
{
47
const bool WRITE_VECTORS = false;
48
}
49
50
51
namespace ns3
45
namespace ns3
52
{
46
{
53
namespace olsr
47
namespace olsr
 Lines 84-93    Link Here 
84
  Simulator::Run ();
78
  Simulator::Run ();
85
  Simulator::Destroy ();
79
  Simulator::Destroy ();
86
80
87
  if (!WRITE_VECTORS)
81
  CheckResults ();  
88
    {
89
      CheckResults ();
90
    }
91
}
82
}
92
83
93
void
84
void
 Lines 172-179    Link Here 
172
  p.Stop (Seconds (SimTime) - Seconds (0.001));
163
  p.Stop (Seconds (SimTime) - Seconds (0.001));
173
164
174
  // pcap
165
  // pcap
175
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : GetTempDir ()) + PREFIX;
166
  wifiPhy.EnablePcapAll (CreateTempDirFilename (PREFIX));
176
  wifiPhy.EnablePcapAll (prefix);
177
}
167
}
178
168
179
void
169
void
 Lines 181-195    Link Here 
181
{
171
{
182
  for (uint32_t i = 0; i < 2; ++i)
172
  for (uint32_t i = 0; i < 2; ++i)
183
    {
173
    {
184
      std::ostringstream os1, os2;
174
      NS_PCAP_TEST_EXPECT_EQ (PREFIX << "-" << i << "-0.pcap");
185
      // File naming conventions are hard-coded here.
186
      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-0.pcap";
187
      os2 << GetTempDir () << PREFIX << "-" << i << "-0.pcap";
188
189
      uint32_t sec (0), usec (0);
190
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec);
191
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
192
                                                         << " differ starting from " << sec << " s " << usec << " us");
193
    }
175
    }
194
}
176
}
195
177
(-)a/src/olsr/test/hello-regression-test.cc (-15 / +4 lines)
 Lines 30-38    Link Here 
30
#include "ns3/point-to-point-helper.h"
30
#include "ns3/point-to-point-helper.h"
31
#include "ns3/ipv4-address-helper.h"
31
#include "ns3/ipv4-address-helper.h"
32
#include "ns3/abort.h"
32
#include "ns3/abort.h"
33
33
#include "ns3/pcap-test.h"
34
/// Set to true to rewrite reference traces, leave false to run regression tests
35
const bool WRITE_VECTORS = false;
36
34
37
namespace ns3
35
namespace ns3
38
{
36
{
 Lines 61-67    Link Here 
61
  Simulator::Run ();
59
  Simulator::Run ();
62
  Simulator::Destroy ();
60
  Simulator::Destroy ();
63
61
64
  if (!WRITE_VECTORS) CheckResults ();
62
  CheckResults ();
65
}
63
}
66
64
67
void
65
void
 Lines 85-92    Link Here 
85
  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
83
  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
86
  ipv4.Assign (nd);
84
  ipv4.Assign (nd);
87
  // setup PCAP traces
85
  // setup PCAP traces
88
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : GetTempDir ()) + PREFIX;
86
  p2p.EnablePcapAll (CreateTempDirFilename (PREFIX));
89
  p2p.EnablePcapAll (prefix);
90
}
87
}
91
88
92
void
89
void
 Lines 94-108    Link Here 
94
{
91
{
95
  for (uint32_t i = 0; i < 2; ++i)
92
  for (uint32_t i = 0; i < 2; ++i)
96
    {
93
    {
97
      std::ostringstream os1, os2;
94
      NS_PCAP_TEST_EXPECT_EQ (PREFIX << "-" << i << "-1.pcap");
98
      // File naming conventions are hard-coded here.
99
      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-1.pcap";
100
      os2 << GetTempDir () << PREFIX << "-" << i << "-1.pcap";
101
102
      uint32_t sec (0), usec (0);
103
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec);
104
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
105
                                                         << " differ starting from " << sec << " s " << usec << " us");
106
    }
95
    }
107
}
96
}
108
97
(-)a/src/olsr/test/regression-test-suite.cc (+1 lines)
 Lines 30-35    Link Here 
30
public:
30
public:
31
  RegressionTestSuite () : TestSuite ("routing-olsr-regression", SYSTEM) 
31
  RegressionTestSuite () : TestSuite ("routing-olsr-regression", SYSTEM) 
32
  {
32
  {
33
    SetDataDir (NS_TEST_SOURCEDIR);
33
    AddTestCase (new HelloRegressionTest);
34
    AddTestCase (new HelloRegressionTest);
34
    AddTestCase (new TcRegressionTest);
35
    AddTestCase (new TcRegressionTest);
35
    AddTestCase (new Bug780Test);
36
    AddTestCase (new Bug780Test);
(-)a/src/olsr/test/tc-regression-test.cc (-15 / +4 lines)
 Lines 25-30    Link Here 
25
#include "ns3/double.h"
25
#include "ns3/double.h"
26
#include "ns3/uinteger.h"
26
#include "ns3/uinteger.h"
27
#include "ns3/string.h"
27
#include "ns3/string.h"
28
#include "ns3/pcap-test.h"
28
#include "ns3/pcap-file.h"
29
#include "ns3/pcap-file.h"
29
#include "ns3/olsr-helper.h"
30
#include "ns3/olsr-helper.h"
30
#include "ns3/internet-stack-helper.h"
31
#include "ns3/internet-stack-helper.h"
 Lines 35-43    Link Here 
35
#include "ns3/mobility-helper.h"
36
#include "ns3/mobility-helper.h"
36
#include "ns3/nqos-wifi-mac-helper.h"
37
#include "ns3/nqos-wifi-mac-helper.h"
37
38
38
/// Set to true to rewrite reference traces, leave false to run regression tests
39
const bool WRITE_VECTORS = false;
40
41
namespace ns3
39
namespace ns3
42
{
40
{
43
namespace olsr
41
namespace olsr
 Lines 66-72    Link Here 
66
  Simulator::Run ();
64
  Simulator::Run ();
67
  Simulator::Destroy ();
65
  Simulator::Destroy ();
68
66
69
  if (!WRITE_VECTORS) CheckResults ();
67
  CheckResults ();
70
}
68
}
71
69
72
void
70
void
 Lines 113-120    Link Here 
113
  ipv4.Assign (nd);
111
  ipv4.Assign (nd);
114
112
115
  // setup PCAP traces
113
  // setup PCAP traces
116
  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : GetTempDir ()) + PREFIX;
114
  wifiPhy.EnablePcapAll (CreateTempDirFilename(PREFIX));
117
  wifiPhy.EnablePcapAll (prefix);
118
}
115
}
119
116
120
void
117
void
 Lines 122-136    Link Here 
122
{
119
{
123
  for (uint32_t i = 0; i < 3; ++i)
120
  for (uint32_t i = 0; i < 3; ++i)
124
    {
121
    {
125
      std::ostringstream os1, os2;
122
      NS_PCAP_TEST_EXPECT_EQ (PREFIX << "-" << i << "-1.pcap");
126
      // File naming conventions are hard-coded here.
127
      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-1.pcap";
128
      os2 << GetTempDir () << PREFIX << "-" << i << "-1.pcap";
129
130
      uint32_t sec (0), usec (0);
131
      bool diff = PcapFile::Diff (os1.str (), os2.str (), sec, usec);
132
      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str () << " and " << os2.str ()
133
                                                         << " differ starting from " << sec << " s " << usec << " us");
134
    }
123
    }
135
}
124
}
136
125
(-)a/src/olsr/wscript (-2 / +3 lines)
 Lines 10-17    Link Here 
10
        'helper/olsr-helper.cc',
10
        'helper/olsr-helper.cc',
11
        ]
11
        ]
12
12
13
    module_test = bld.create_ns3_module_test_library('olsr')
13
    module_test_source = [
14
    module_test.source = [
15
        'test/bug780-test.cc',
14
        'test/bug780-test.cc',
16
        'test/hello-regression-test.cc',
15
        'test/hello-regression-test.cc',
17
        'test/olsr-header-test-suite.cc',
16
        'test/olsr-header-test-suite.cc',
 Lines 19-24    Link Here 
19
        'test/olsr-routing-protocol-test-suite.cc',
18
        'test/olsr-routing-protocol-test-suite.cc',
20
        'test/tc-regression-test.cc',
19
        'test/tc-regression-test.cc',
21
        ]
20
        ]
21
    module_test = bld.create_ns3_module_test_library('olsr',
22
                                                     module_test_source)
22
23
23
    headers = bld.new_task_gen('ns3header')
24
    headers = bld.new_task_gen('ns3header')
24
    headers.module = 'olsr'
25
    headers.module = 'olsr'
(-)a/src/openflow/wscript (-11 / +1 lines)
 Lines 148-164    Link Here 
148
148
149
    headers = bld.new_task_gen('ns3header')
149
    headers = bld.new_task_gen('ns3header')
150
    headers.module = 'openflow'
150
    headers.module = 'openflow'
151
    headers.source = [
151
    headers.source = headers_source
152
        ]
153
154
    if bld.env['ENABLE_OPENFLOW']:
155
	obj.source.append('model/openflow-interface.cc')
156
        obj.source.append('model/openflow-switch-net-device.cc')
157
	obj.source.append('helper/openflow-switch-helper.cc')
158
	obj_test.source.append('test/openflow-switch-test-suite.cc')
159
	headers.source.append('model/openflow-interface.h')
160
        headers.source.append('model/openflow-switch-net-device.h')
161
	headers.source.append('helper/openflow-switch-helper.h')
162
152
163
    if bld.env['ENABLE_EXAMPLES'] and bld.env['ENABLE_OPENFLOW']:
153
    if bld.env['ENABLE_EXAMPLES'] and bld.env['ENABLE_OPENFLOW']:
164
        bld.add_subdirs('examples')
154
        bld.add_subdirs('examples')
(-)a/src/point-to-point/wscript (-2 / +3 lines)
 Lines 11-20    Link Here 
11
        'helper/point-to-point-helper.cc',
11
        'helper/point-to-point-helper.cc',
12
        ]
12
        ]
13
13
14
    module_test = bld.create_ns3_module_test_library('point-to-point')
14
    module_test_source = [
15
    module_test.source = [
16
        'test/point-to-point-test.cc',
15
        'test/point-to-point-test.cc',
17
        ]
16
        ]
17
    module_test = bld.create_ns3_module_test_library('point-to-point',
18
                                                     module_test_source)
18
19
19
    headers = bld.new_task_gen('ns3header')
20
    headers = bld.new_task_gen('ns3header')
20
    headers.module = 'point-to-point'
21
    headers.module = 'point-to-point'
(-)a/src/propagation/wscript (-2 / +3 lines)
 Lines 10-19    Link Here 
10
        'model/cost231-propagation-loss-model.cc',
10
        'model/cost231-propagation-loss-model.cc',
11
        ]
11
        ]
12
12
13
    module_test = bld.create_ns3_module_test_library('propagation')
13
    module_test_source = [
14
    module_test.source = [
15
        'test/propagation-loss-model-test-suite.cc',
14
        'test/propagation-loss-model-test-suite.cc',
16
        ]
15
        ]
16
    module_test = bld.create_ns3_module_test_library('propagation',
17
                                                     module_test_source)
17
18
18
    headers = bld.new_task_gen('ns3header')
19
    headers = bld.new_task_gen('ns3header')
19
    headers.module = 'propagation'
20
    headers.module = 'propagation'
(-)a/src/spectrum/test/spectrum-test.h (-2 / +5 lines)
 Lines 56-62    Link Here 
56
              || (i->fc > j->fc + (tol)) || (i->fc < j->fc - (tol))        \
56
              || (i->fc > j->fc + (tol)) || (i->fc < j->fc - (tol))        \
57
              || (i->fh > j->fh + (tol)) || (i->fh < j->fh - (tol)))       \
57
              || (i->fh > j->fh + (tol)) || (i->fh < j->fh - (tol)))       \
58
            {                                           \
58
            {                                           \
59
              if (gBreakOnFailure) { *(int *)0 = 0; }     \
59
              ASSERT_ON_FAILURE;                        \
60
              std::ostringstream indexStream;           \
60
              std::ostringstream indexStream;           \
61
              indexStream << "[" << k << "]";           \
61
              indexStream << "[" << k << "]";           \
62
              std::ostringstream msgStream;     \
62
              std::ostringstream msgStream;     \
 Lines 67-72    Link Here 
67
              expectedStream << j->fl << " <-- " << j->fc << " --> " << j->fh;          \
67
              expectedStream << j->fl << " <-- " << j->fc << " --> " << j->fh;          \
68
              ReportTestFailure (std::string (# actual) + indexStream.str () + " == " + std::string (# expected) + indexStream.str (),    \
68
              ReportTestFailure (std::string (# actual) + indexStream.str () + " == " + std::string (# expected) + indexStream.str (),    \
69
                                 actualStream.str (), expectedStream.str (), msgStream.str (), (file), (line)); \
69
                                 actualStream.str (), expectedStream.str (), msgStream.str (), (file), (line)); \
70
              CONTINUE_ON_FAILURE;                                      \
71
70
            }                   \
72
            }                   \
71
          ++i;   \
73
          ++i;   \
72
          ++j;   \
74
          ++j;   \
 Lines 117-123    Link Here 
117
        {                                                                      \
119
        {                                                                      \
118
          if ((*i) > (*j) + (tol) || (*i) < (*j) - (tol))                      \
120
          if ((*i) > (*j) + (tol) || (*i) < (*j) - (tol))                      \
119
            {                                           \
121
            {                                           \
120
              if (gBreakOnFailure) { *(int *)0 = 0; }     \
122
              ASSERT_ON_FAILURE;                        \
121
              std::ostringstream indexStream;           \
123
              std::ostringstream indexStream;           \
122
              indexStream << "[" << k << "]";           \
124
              indexStream << "[" << k << "]";           \
123
              std::ostringstream msgStream;     \
125
              std::ostringstream msgStream;     \
 Lines 128-133    Link Here 
128
              expectedStream << expected;               \
130
              expectedStream << expected;               \
129
              ReportTestFailure (std::string (# actual) + indexStream.str () + " == " + std::string (# expected) + indexStream.str (),    \
131
              ReportTestFailure (std::string (# actual) + indexStream.str () + " == " + std::string (# expected) + indexStream.str (),    \
130
                                 actualStream.str (), expectedStream.str (), msgStream.str (), file, line);     \
132
                                 actualStream.str (), expectedStream.str (), msgStream.str (), file, line);     \
133
              CONTINUE_ON_FAILURE;                                      \
131
            }                   \
134
            }                   \
132
          ++i;   \
135
          ++i;   \
133
          ++j;   \
136
          ++j;   \
(-)a/src/spectrum/test/spectrum-value-test.cc (-2 / +2 lines)
 Lines 72-79    Link Here 
72
void
72
void
73
SpectrumValueTestCase::DoRun (void)
73
SpectrumValueTestCase::DoRun (void)
74
{
74
{
75
  NS_TEST_ASSERT_MSG_SPECTRUM_MODEL_EQ_TOL (*m_a.GetSpectrumModel (), *m_b.GetSpectrumModel (), TOLERANCE, GetName ());
75
  NS_TEST_ASSERT_MSG_SPECTRUM_MODEL_EQ_TOL (*m_a.GetSpectrumModel (), *m_b.GetSpectrumModel (), TOLERANCE, "");
76
  NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL (m_a, m_b, TOLERANCE, GetName ());
76
  NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL (m_a, m_b, TOLERANCE, "");
77
}
77
}
78
78
79
79
(-)a/src/spectrum/wscript (-2 / +3 lines)
 Lines 32-43    Link Here 
32
        'helper/spectrum-analyzer-helper.cc',
32
        'helper/spectrum-analyzer-helper.cc',
33
        ]
33
        ]
34
34
35
    module_test = bld.create_ns3_module_test_library('spectrum')
35
    module_test_source = [
36
    module_test.source = [
37
        'test/spectrum-interference-test.cc',
36
        'test/spectrum-interference-test.cc',
38
        'test/spectrum-value-test.cc',
37
        'test/spectrum-value-test.cc',
39
        'test/spectrum-ideal-phy-test.cc',
38
        'test/spectrum-ideal-phy-test.cc',
40
        ]
39
        ]
40
    module_test = bld.create_ns3_module_test_library('spectrum',
41
                                                     module_test_source)
41
    
42
    
42
    headers = bld.new_task_gen('ns3header')
43
    headers = bld.new_task_gen('ns3header')
43
    headers.module = 'spectrum'
44
    headers.module = 'spectrum'
(-)a/src/stats/wscript (-2 / +2 lines)
 Lines 18-27    Link Here 
18
        'model/data-collector.cc',
18
        'model/data-collector.cc',
19
        ]
19
        ]
20
20
21
    module_test = bld.create_ns3_module_test_library('stats')
21
    module_test_source = [
22
    module_test.source = [
23
        'test/basic-data-calculators-test-suite.cc',
22
        'test/basic-data-calculators-test-suite.cc',
24
        ]
23
        ]
24
    module_test = bld.create_ns3_module_test_library('stats', module_test_source)
25
25
26
    headers = bld.new_task_gen('ns3header')
26
    headers = bld.new_task_gen('ns3header')
27
    headers.module = 'stats'
27
    headers.module = 'stats'
(-)a/src/template/wscript (-4 / +4 lines)
 Lines 16-30    Link Here 
16
        #'helper/sample-helper-2.cc',
16
        #'helper/sample-helper-2.cc',
17
        ]
17
        ]
18
18
19
    # Create the module's test library.
20
    module_test = bld.create_ns3_module_test_library('template')
21
22
    # Set the C++ source files for the module's test library.
19
    # Set the C++ source files for the module's test library.
23
    module_test.source = [
20
    test_library_source = [
24
        # Uncomment these lines to compile these test suites.
21
        # Uncomment these lines to compile these test suites.
25
        #'test/sample-test-suite-1.cc',
22
        #'test/sample-test-suite-1.cc',
26
        #'test/sample-test-suite-2.cc',
23
        #'test/sample-test-suite-2.cc',
27
        ]
24
        ]
25
    # Create the module's test library.
26
    test_library = bld.create_ns3_module_test_library('template', test_library_source)
27
28
28
29
    # Make headers be installed for this module.
29
    # Make headers be installed for this module.
30
    headers = bld.new_task_gen('ns3header')
30
    headers = bld.new_task_gen('ns3header')
(-)a/src/test/ns3tcp/ns3tcp-interop-test-suite.cc (-1 / +1 lines)
 Lines 184-190    Link Here 
184
      //
184
      //
185
      // Avoid streams of errors -- only report the first.
185
      // Avoid streams of errors -- only report the first.
186
      //
186
      //
187
      if (GetErrorStatus () == false)
187
      if (IsStatusSuccess ())
188
        {
188
        {
189
          NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error");
189
          NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error");
190
        }
190
        }
(-)a/src/test/ns3tcp/ns3tcp-loss-test-suite.cc (-2 / +5 lines)
 Lines 121-127    Link Here 
121
  //
121
  //
122
  std::ostringstream oss;
122
  std::ostringstream oss;
123
  oss << "/response-vectors/ns3tcp-loss-" << m_tcpModel << m_testCase << "-response-vectors.pcap";
123
  oss << "/response-vectors/ns3tcp-loss-" << m_tcpModel << m_testCase << "-response-vectors.pcap";
124
  m_pcapFilename = NS_TEST_SOURCEDIR + oss.str ();
124
    m_pcapFilename = CreateDataDirFilename(oss.str ());
125
125
126
  if (m_writeVectors)
126
  if (m_writeVectors)
127
    {
127
    {
 Lines 185-190    Link Here 
185
      uint32_t tsSec, tsUsec, inclLen, origLen, readLen;
185
      uint32_t tsSec, tsUsec, inclLen, origLen, readLen;
186
      m_pcapFile.Read (expected, sizeof(expected), tsSec, tsUsec, inclLen, origLen, readLen);
186
      m_pcapFile.Read (expected, sizeof(expected), tsSec, tsUsec, inclLen, origLen, readLen);
187
187
188
      NS_LOG_DEBUG ("read " << readLen);
189
188
      uint8_t *actual = new uint8_t[readLen];
190
      uint8_t *actual = new uint8_t[readLen];
189
      p->CopyData (actual, readLen);
191
      p->CopyData (actual, readLen);
190
192
 Lines 195-201    Link Here 
195
      //
197
      //
196
      // Avoid streams of errors -- only report the first.
198
      // Avoid streams of errors -- only report the first.
197
      //
199
      //
198
      if (GetErrorStatus () == false)
200
      if (IsStatusSuccess ())
199
        {
201
        {
200
          NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error");
202
          NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error");
201
        }
203
        }
 Lines 442-447    Link Here 
442
Ns3TcpLossTestSuite::Ns3TcpLossTestSuite ()
444
Ns3TcpLossTestSuite::Ns3TcpLossTestSuite ()
443
  : TestSuite ("ns3-tcp-loss", SYSTEM)
445
  : TestSuite ("ns3-tcp-loss", SYSTEM)
444
{
446
{
447
  SetDataDir (NS_TEST_SOURCEDIR);
445
  Packet::EnablePrinting ();  // Enable packet metadata for all test cases
448
  Packet::EnablePrinting ();  // Enable packet metadata for all test cases
446
  AddTestCase (new Ns3TcpLossTestCase ("Tahoe", 0));
449
  AddTestCase (new Ns3TcpLossTestCase ("Tahoe", 0));
447
  AddTestCase (new Ns3TcpLossTestCase ("Tahoe", 1));
450
  AddTestCase (new Ns3TcpLossTestCase ("Tahoe", 1));
(-)a/src/test/ns3tcp/ns3tcp-state-test-suite.cc (-1 / +1 lines)
 Lines 190-196    Link Here 
190
      //
190
      //
191
      // Avoid streams of errors -- only report the first.
191
      // Avoid streams of errors -- only report the first.
192
      //
192
      //
193
      if (GetErrorStatus () == false)
193
      if (IsStatusSuccess ())
194
        {
194
        {
195
          NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error");
195
          NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error");
196
        }
196
        }
(-)a/src/test/ns3tcp/wscript (-2 / +3 lines)
 Lines 22-34    Link Here 
22
        'ns3tcp.h',
22
        'ns3tcp.h',
23
        ]
23
        ]
24
24
25
    ns3tcp_test = bld.create_ns3_module_test_library('ns3tcp')
25
    ns3tcp_test_source = [
26
    ns3tcp_test.source = [
27
        'ns3tcp-socket-writer.cc',
26
        'ns3tcp-socket-writer.cc',
28
        'ns3tcp-socket-test-suite.cc',
27
        'ns3tcp-socket-test-suite.cc',
29
        'ns3tcp-loss-test-suite.cc',
28
        'ns3tcp-loss-test-suite.cc',
30
        'ns3tcp-state-test-suite.cc',
29
        'ns3tcp-state-test-suite.cc',
31
        ]
30
        ]
31
    ns3tcp_test = bld.create_ns3_module_test_library('ns3tcp',
32
                                                     ns3tcp_test_source)
32
33
33
    if bld.env['NSC_ENABLED']:
34
    if bld.env['NSC_ENABLED']:
34
        ns3tcp_test.source.append ('ns3tcp-interop-test-suite.cc')
35
        ns3tcp_test.source.append ('ns3tcp-interop-test-suite.cc')
(-)a/src/test/ns3wifi/wscript (-2 / +3 lines)
 Lines 22-30    Link Here 
22
        'ns3wifi.h',
22
        'ns3wifi.h',
23
        ]
23
        ]
24
24
25
    ns3wifi_test = bld.create_ns3_module_test_library('ns3wifi')
25
    ns3wifi_test_source = [
26
    ns3wifi_test.source = [
27
        'wifi-interference-test-suite.cc',
26
        'wifi-interference-test-suite.cc',
28
        'wifi-msdu-aggregator-test-suite.cc',
27
        'wifi-msdu-aggregator-test-suite.cc',
29
        ]
28
        ]
29
    ns3wifi_test = bld.create_ns3_module_test_library('ns3wifi',
30
                                                      ns3wifi_test_source)
30
31
(-)a/src/test/wscript (-2 / +3 lines)
 Lines 23-34    Link Here 
23
    headers = bld.new_task_gen('ns3header')
23
    headers = bld.new_task_gen('ns3header')
24
    headers.module = 'test'
24
    headers.module = 'test'
25
25
26
    test_test = bld.create_ns3_module_test_library('test')
26
    test_test_source = [
27
    test_test.source = [
28
        'csma-system-test-suite.cc',
27
        'csma-system-test-suite.cc',
29
        'global-routing-test-suite.cc',
28
        'global-routing-test-suite.cc',
30
        'static-routing-test-suite.cc',
29
        'static-routing-test-suite.cc',
31
        'error-model-test-suite.cc',
30
        'error-model-test-suite.cc',
32
        'mobility-test-suite.cc',
31
        'mobility-test-suite.cc',
33
        ]
32
        ]
33
    test_test = bld.create_ns3_module_test_library('test',
34
                                                   test_test_source)
34
35
(-)a/src/tools/wscript (-2 / +3 lines)
 Lines 9-18    Link Here 
9
        'model/delay-jitter-estimation.cc',
9
        'model/delay-jitter-estimation.cc',
10
        ]
10
        ]
11
11
12
    module_test = bld.create_ns3_module_test_library('tools')
12
    module_test_source = [
13
    module_test.source = [
14
        'test/event-garbage-collector-test-suite.cc',
13
        'test/event-garbage-collector-test-suite.cc',
15
        ]
14
        ]
15
    module_test = bld.create_ns3_module_test_library('tools',
16
                                                     module_test_source)
16
    
17
    
17
    headers = bld.new_task_gen('ns3header')
18
    headers = bld.new_task_gen('ns3header')
18
    headers.module = 'tools'
19
    headers.module = 'tools'
(-)a/src/topology-read/wscript (-2 / +3 lines)
 Lines 10-19    Link Here 
10
       'helper/topology-reader-helper.cc',
10
       'helper/topology-reader-helper.cc',
11
        ]
11
        ]
12
12
13
    module_test = bld.create_ns3_module_test_library('topology-read')
13
    module_test_source = [
14
    module_test.source = [
15
        'test/rocketfuel-topology-reader-test-suite.cc',
14
        'test/rocketfuel-topology-reader-test-suite.cc',
16
        ]
15
        ]
16
    module_test = bld.create_ns3_module_test_library('topology-read',
17
                                                     module_test_source)
17
18
18
    headers = bld.new_task_gen('ns3header')
19
    headers = bld.new_task_gen('ns3header')
19
    headers.module = 'topology-read'
20
    headers.module = 'topology-read'
(-)a/src/uan/wscript (-2 / +3 lines)
 Lines 27-37    Link Here 
27
        'helper/acoustic-modem-energy-model-helper.cc',
27
        'helper/acoustic-modem-energy-model-helper.cc',
28
        ]
28
        ]
29
29
30
    module_test = bld.create_ns3_module_test_library('uan')
30
    module_test_source = [
31
    module_test.source = [
32
        'test/uan-test.cc',
31
        'test/uan-test.cc',
33
        'test/uan-energy-model-test.cc',
32
        'test/uan-energy-model-test.cc',
34
        ]
33
        ]
34
    module_test = bld.create_ns3_module_test_library('uan', module_test_source)
35
35
    headers = bld.new_task_gen('ns3header')
36
    headers = bld.new_task_gen('ns3header')
36
    headers.module = 'uan'
37
    headers.module = 'uan'
37
    headers.source = [
38
    headers.source = [
(-)a/src/wifi/wscript (-3 / +3 lines)
 Lines 67-79    Link Here 
67
        'helper/qos-wifi-mac-helper.cc',
67
        'helper/qos-wifi-mac-helper.cc',
68
        ]
68
        ]
69
69
70
    obj_test = bld.create_ns3_module_test_library('wifi')
70
    obj_test_source = [
71
    obj_test.source = [
72
        'test/block-ack-test-suite.cc',
71
        'test/block-ack-test-suite.cc',
73
        'test/dcf-manager-test.cc',
72
        'test/dcf-manager-test.cc',
74
        'test/tx-duration-test.cc',
73
        'test/tx-duration-test.cc',
75
        'test/wifi-test.cc',
74
        'test/wifi-test.cc'
76
        ]
75
        ]
76
    obj_test = bld.create_ns3_module_test_library('wifi', obj_test_source)
77
77
78
    headers = bld.new_task_gen('ns3header')
78
    headers = bld.new_task_gen('ns3header')
79
    headers.module = 'wifi'
79
    headers.module = 'wifi'
(-)a/src/wimax/wscript (-2 / +3 lines)
 Lines 52-59    Link Here 
52
            'helper/wimax-helper.cc',
52
            'helper/wimax-helper.cc',
53
		            ]
53
		            ]
54
54
55
    obj_test = bld.create_ns3_module_test_library('wimax')
55
    obj_test_source = [
56
    obj_test.source = [
57
            'test/wimax-tlv-test.cc',
56
            'test/wimax-tlv-test.cc',
58
            'test/mac-messages-test.cc',
57
            'test/mac-messages-test.cc',
59
            'test/wimax-service-flow-test.cc',
58
            'test/wimax-service-flow-test.cc',
 Lines 62-67    Link Here 
62
            'test/qos-test.cc',
61
            'test/qos-test.cc',
63
            'test/wimax-fragmentation-test.cc',
62
            'test/wimax-fragmentation-test.cc',
64
            ]
63
            ]
64
    obj_test = bld.create_ns3_module_test_library('wimax',
65
                                                  obj_test_source)
65
		            
66
		            
66
    headers = bld.new_task_gen('ns3header')
67
    headers = bld.new_task_gen('ns3header')
67
    headers.module = 'wimax'
68
    headers.module = 'wimax'
(-)a/src/wscript (-1 / +13 lines)
 Lines 223-233    Link Here 
223
    return module
223
    return module
224
224
225
225
226
def create_ns3_module_test_library(bld, name):
226
def create_ns3_module_test_library(bld, name, source):
227
    # Create an ns3 module for the test library that depends only on
227
    # Create an ns3 module for the test library that depends only on
228
    # the module being tested.
228
    # the module being tested.
229
    library_name = name + "-test"
229
    library_name = name + "-test"
230
    library = bld.create_ns3_module(library_name, [name], test = True)
230
    library = bld.create_ns3_module(library_name, [name], test = True)
231
    objects = []
232
    for src in source:
233
        tmp = bld.path.relpath_gen(bld.srcnode)
234
        path = os.path.dirname(os.path.join(tmp, src))
235
        target = '%s_object' % src
236
        # XXX: calculate the features correctly here.
237
        obj = bld (source=[src], target=target, features='cxx cc',
238
                   defines=['NS_TEST_SOURCEDIR="%s"' % path], 
239
                   cxxflags = library.env['CXXFLAGS'], ccflags = library.env['CCFLAGS'])
240
        objects.append(target)
241
    library.add_objects = objects
242
        
231
243
232
    # Modify attributes for the test library that are different from a
244
    # Modify attributes for the test library that are different from a
233
    # normal module.
245
    # normal module.
(-)a/test.py (-88 / +82 lines)
 Lines 165-218    Link Here 
165
#
165
#
166
TMP_OUTPUT_DIR = "testpy-output"
166
TMP_OUTPUT_DIR = "testpy-output"
167
167
168
def get_node_text(node):
168
def read_test(test):
169
    for child in node.childNodes:
169
    result = test.find('Result').text
170
        if child.nodeType == child.TEXT_NODE:
170
    name = test.find('Name').text
171
            return child.nodeValue
171
    if not test.find('Time') is None:
172
    return "None"
172
        time_real = test.find('Time').get('real')
173
    else:
174
        time_real = ''
175
    return (result, name, time_real)
173
176
174
#
177
#
175
# A simple example of writing a text file with a test result summary.  It is 
178
# A simple example of writing a text file with a test result summary.  It is 
176
# expected that this output will be fine for developers looking for problems.
179
# expected that this output will be fine for developers looking for problems.
177
#
180
#
181
def node_to_text (test, f):
182
    (result, name, time) = read_test(test)
183
    output = "%s: Test Suite \"%s\" (%s)\n" % (result, name, time_real)
184
    f.write(output)
185
    for details in test.findall('FailureDetails'):
186
        f.write("    Details:\n")
187
        f.write("      Message:   %s\n" % details.find('Message').text)
188
        f.write("      Condition: %s\n" % details.find('Condition').text)
189
        f.write("      Actual:    %s\n" % details.find('Actual').text)
190
        f.write("      Limit:     %s\n" % details.find('Limit').text)
191
        f.write("      File:      %s\n" % details.find('File').text)
192
        f.write("      Line:      %s\n" % details.find('Line').text)
193
    for child in test.findall('Test'):
194
        node_to_text(child, f)
195
178
def translate_to_text(results_file, text_file):
196
def translate_to_text(results_file, text_file):
179
    f = open(text_file, 'w')
197
    f = open(text_file, 'w')
180
    try:
198
    import xml.etree.ElementTree as ET
181
      dom = xml.dom.minidom.parse(results_file)
199
    et = ET.parse (results_file)
182
    except xml.parsers.expat.error:
200
    for test in et.findall('Test'):
183
      print "\nAn error was encountered while parsing the XML file %s." % (results_file)
201
        node_to_text (test, f)
184
      sys.exit(1)
185
202
186
    for suite in dom.getElementsByTagName("TestSuite"):
203
    for example in et.findall('Example'):
187
        result = get_node_text(suite.getElementsByTagName("SuiteResult")[0])
204
        result = example.find('Result').text
188
        name = get_node_text(suite.getElementsByTagName("SuiteName")[0])
205
        name = example.find('Name').text
189
        time = get_node_text(suite.getElementsByTagName("SuiteTime")[0])
206
        if not example.find('Time') is None:
190
        output = "%s: Test Suite \"%s\" (%s)\n" % (result, name, time)
207
            time_real = example.find('Time').get('real')
191
        f.write(output)
208
        else:
192
        if result != "CRASH":
209
            time_real = ''
193
            for case in suite.getElementsByTagName("TestCase"):
210
        output = "%s: Example \"%s\" (%s)\n" % (result, name, time_real)
194
                result = get_node_text(case.getElementsByTagName("CaseResult")[0])
211
         f.write(output)
195
                name = get_node_text(case.getElementsByTagName("CaseName")[0])
196
                time = get_node_text(case.getElementsByTagName("CaseTime")[0])
197
                output =   "  %s: Test Case \"%s\" (%s)\n" % (result, name, time)
198
                f.write(output)
199
200
                if result == "FAIL":
201
                    for details in case.getElementsByTagName("FailureDetails"):
202
                        f.write("    Details:\n")
203
                        f.write("      Message:   %s\n" % get_node_text(details.getElementsByTagName("Message")[0]))
204
                        f.write("      Condition: %s\n" % get_node_text(details.getElementsByTagName("Condition")[0]))
205
                        f.write("      Actual:    %s\n" % get_node_text(details.getElementsByTagName("Actual")[0]))
206
                        f.write("      Limit:     %s\n" % get_node_text(details.getElementsByTagName("Limit")[0]))
207
                        f.write("      File:      %s\n" % get_node_text(details.getElementsByTagName("File")[0]))
208
                        f.write("      Line:      %s\n" % get_node_text(details.getElementsByTagName("Line")[0]))
209
210
    for example in dom.getElementsByTagName("Example"):
211
        result = get_node_text(example.getElementsByTagName("Result")[0])
212
        name = get_node_text(example.getElementsByTagName("Name")[0])
213
        time = get_node_text(example.getElementsByTagName("ElapsedTime")[0])
214
        output = "%s: Example \"%s\" (%s)\n" % (result, name, time)
215
        f.write(output)
216
212
217
    f.close()
213
    f.close()
218
    
214
    
 Lines 231-250    Link Here 
231
    #
227
    #
232
    # Read and parse the whole results file.
228
    # Read and parse the whole results file.
233
    #
229
    #
234
    dom = xml.dom.minidom.parse(results_file)
230
    import xml.etree.ElementTree as ET
231
    et = ET.parse(results_file)
235
232
236
    #
233
    #
237
    # Iterate through the test suites
234
    # Iterate through the test suites
238
    #
235
    #
239
    f.write("<h2>Test Suites</h2>\n")
236
    f.write("<h2>Test Suites</h2>\n")
240
    for suite in dom.getElementsByTagName("TestSuite"):
237
    for suite in et.findall('Test'):     
241
     
242
        #
238
        #
243
        # For each test suite, get its name, result and execution time info
239
        # For each test suite, get its name, result and execution time info
244
        #
240
        #
245
        name = get_node_text(suite.getElementsByTagName("SuiteName")[0])
241
        (result, name, time) = read_test (suite)
246
        result = get_node_text(suite.getElementsByTagName("SuiteResult")[0])
247
        time = get_node_text(suite.getElementsByTagName("SuiteTime")[0])
248
242
249
        # 
243
        # 
250
        # Print a level three header with the result, name and time.  If the 
244
        # Print a level three header with the result, name and time.  If the 
 Lines 316-330    Link Here 
316
        #
310
        #
317
        # Now iterate through all of the test cases.
311
        # Now iterate through all of the test cases.
318
        #
312
        #
319
        for case in suite.getElementsByTagName("TestCase"):
313
        for case in suite.findall('Test'):
320
314
321
            #
315
            #
322
            # Get the name, result and timing information from xml to use in
316
            # Get the name, result and timing information from xml to use in
323
            # printing table below.
317
            # printing table below.
324
            #
318
            #
325
            name = get_node_text(case.getElementsByTagName("CaseName")[0])
319
            (result, name, time) = read_test(case)
326
            result = get_node_text(case.getElementsByTagName("CaseResult")[0])
327
            time = get_node_text(case.getElementsByTagName("CaseTime")[0])
328
320
329
            #
321
            #
330
            # If the test case failed, we iterate through possibly multiple
322
            # If the test case failed, we iterate through possibly multiple
 Lines 349-355    Link Here 
349
                #
341
                #
350
342
351
                first_row = True
343
                first_row = True
352
                for details in case.getElementsByTagName("FailureDetails"):
344
                for details in case.findall('FailureDetails'):
353
345
354
                    #
346
                    #
355
                    # Start a new row in the table for each possible Failure Detail
347
                    # Start a new row in the table for each possible Failure Detail
 Lines 367-378    Link Here 
367
                        f.write("<td></td>\n")
359
                        f.write("<td></td>\n")
368
360
369
                    f.write("<td>")
361
                    f.write("<td>")
370
                    f.write("<b>Message: </b>%s, " % get_node_text(details.getElementsByTagName("Message")[0]))
362
                    f.write("<b>Message: </b>%s, " % details.find('Message').text)
371
                    f.write("<b>Condition: </b>%s, " % get_node_text(details.getElementsByTagName("Condition")[0]))
363
                    f.write("<b>Condition: </b>%s, " % details.find('Condition').text)
372
                    f.write("<b>Actual: </b>%s, " % get_node_text(details.getElementsByTagName("Actual")[0]))
364
                    f.write("<b>Actual: </b>%s, " % details.find('Actual').text)
373
                    f.write("<b>Limit: </b>%s, " % get_node_text(details.getElementsByTagName("Limit")[0]))
365
                    f.write("<b>Limit: </b>%s, " % details.find('Limit').text)
374
                    f.write("<b>File: </b>%s, " % get_node_text(details.getElementsByTagName("File")[0]))
366
                    f.write("<b>File: </b>%s, " % details.find('File').text)
375
                    f.write("<b>Line: </b>%s" % get_node_text(details.getElementsByTagName("Line")[0]))
367
                    f.write("<b>Line: </b>%s" % details.find('Line').text)
376
                    f.write("</td>\n")
368
                    f.write("</td>\n")
377
                    
369
                    
378
                    #
370
                    #
 Lines 428-434    Link Here 
428
    #
420
    #
429
    # Now iterate through all of the examples
421
    # Now iterate through all of the examples
430
    #
422
    #
431
    for example in dom.getElementsByTagName("Example"):
423
    for example in et.findall("Example"):
432
        
424
        
433
        #
425
        #
434
        # Start a new row for each example
426
        # Start a new row for each example
 Lines 438-446    Link Here 
438
        #
430
        #
439
        # Get the result and name of the example in question
431
        # Get the result and name of the example in question
440
        #
432
        #
441
        result = get_node_text(example.getElementsByTagName("Result")[0])
433
        (result, name, time) = read_test(example)
442
        name =   get_node_text(example.getElementsByTagName("Name")[0])
443
        time =   get_node_text(example.getElementsByTagName("ElapsedTime")[0])
444
434
445
        #
435
        #
446
        # If the example either failed or crashed, print its result status
436
        # If the example either failed or crashed, print its result status
 Lines 786-792    Link Here 
786
    #
776
    #
787
    # This is the shell command that will be executed in the job.  For example,
777
    # This is the shell command that will be executed in the job.  For example,
788
    #
778
    #
789
    #  "utils/test-runner --suite=some-test-suite"
779
    #  "utils/test-runner --test-name=some-test-suite"
790
    #
780
    #
791
    def set_shell_command(self, shell_command):
781
    def set_shell_command(self, shell_command):
792
        self.shell_command = shell_command
782
        self.shell_command = shell_command
 Lines 919-926    Link Here 
919
                    # to the test runner, specifically the base directory and temp
909
                    # to the test runner, specifically the base directory and temp
920
                    # file name
910
                    # file name
921
                    #
911
                    #
912
                    if options.update_data:
913
                        update_data = '--update-data'
914
                    else:
915
                        update_data = ''
922
                    (job.returncode, standard_out, standard_err, et) = run_job_synchronously(job.shell_command + 
916
                    (job.returncode, standard_out, standard_err, et) = run_job_synchronously(job.shell_command + 
923
                        " --basedir=%s --tempdir=%s --out=%s" % (job.basedir, job.tempdir, job.tmp_file_name), 
917
                        " --xml --tempdir=%s --out=%s %s" % (job.tempdir, job.tmp_file_name, update_data), 
924
                        job.cwd, options.valgrind, False)
918
                        job.cwd, options.valgrind, False)
925
919
926
                job.set_elapsed_time(et)
920
                job.set_elapsed_time(et)
 Lines 1063-1074    Link Here 
1063
    # handle them without doing all of the hard work.
1057
    # handle them without doing all of the hard work.
1064
    #
1058
    #
1065
    if options.kinds:
1059
    if options.kinds:
1066
        path_cmd = os.path.join("utils", "test-runner --kinds")
1060
        path_cmd = os.path.join("utils", "test-runner --print-test-type-list")
1067
        (rc, standard_out, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False, False)
1061
        (rc, standard_out, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False, False)
1068
        print standard_out
1062
        print standard_out
1069
1063
1070
    if options.list:
1064
    if options.list:
1071
        path_cmd = os.path.join("utils", "test-runner --list")
1065
        path_cmd = os.path.join("utils", "test-runner --print-test-name-list")
1072
        (rc, standard_out, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False, False)
1066
        (rc, standard_out, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False, False)
1073
        print standard_out
1067
        print standard_out
1074
1068
 Lines 1113-1119    Link Here 
1113
    xml_results_file = os.path.join(testpy_output_dir, "results.xml")
1107
    xml_results_file = os.path.join(testpy_output_dir, "results.xml")
1114
    f = open(xml_results_file, 'w')
1108
    f = open(xml_results_file, 'w')
1115
    f.write('<?xml version="1.0"?>\n')
1109
    f.write('<?xml version="1.0"?>\n')
1116
    f.write('<TestResults>\n')
1110
    f.write('<Results>\n')
1117
    f.close()
1111
    f.close()
1118
1112
1119
    #
1113
    #
 Lines 1141-1150    Link Here 
1141
        suites = options.suite + "\n"
1135
        suites = options.suite + "\n"
1142
    elif len(options.example) == 0 and len(options.pyexample) == 0:
1136
    elif len(options.example) == 0 and len(options.pyexample) == 0:
1143
        if len(options.constrain):
1137
        if len(options.constrain):
1144
            path_cmd = os.path.join("utils", "test-runner --list --constrain=%s" % options.constrain)
1138
            path_cmd = os.path.join("utils", "test-runner --print-test-name-list --test-type=%s" % options.constrain)
1145
            (rc, suites, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False, False)
1139
            (rc, suites, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False, False)
1146
        else:
1140
        else:
1147
            path_cmd = os.path.join("utils", "test-runner --list")
1141
            path_cmd = os.path.join("utils", "test-runner --print-test-name-list")
1148
            (rc, suites, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False, False)
1142
            (rc, suites, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False, False)
1149
    else:
1143
    else:
1150
        suites = ""
1144
        suites = ""
 Lines 1222-1232    Link Here 
1222
            job.set_basedir(os.getcwd())
1216
            job.set_basedir(os.getcwd())
1223
            job.set_tempdir(testpy_output_dir)
1217
            job.set_tempdir(testpy_output_dir)
1224
            if (options.multiple):
1218
            if (options.multiple):
1225
                multiple = " --multiple"
1219
                multiple = ""
1226
            else:
1220
            else:
1227
                multiple = ""
1221
                multiple = " --stop-on-failure"
1228
1222
1229
            path_cmd = os.path.join("utils", "test-runner --suite=%s%s" % (test, multiple))
1223
            path_cmd = os.path.join("utils", "test-runner --test-name=%s%s" % (test, multiple))
1230
            job.set_shell_command(path_cmd)
1224
            job.set_shell_command(path_cmd)
1231
1225
1232
            if options.valgrind and test in core_valgrind_skip_tests:
1226
            if options.valgrind and test in core_valgrind_skip_tests:
 Lines 1510-1516    Link Here 
1510
            else:
1504
            else:
1511
                f.write('  <Result>CRASH</Result>\n')
1505
                f.write('  <Result>CRASH</Result>\n')
1512
1506
1513
            f.write('  <ElapsedTime>%.3f</ElapsedTime>\n' % job.elapsed_time)
1507
            f.write('  <Time real="%.3f"/>\n' % job.elapsed_time)
1514
            f.write('</Example>\n')
1508
            f.write('</Example>\n')
1515
            f.close()
1509
            f.close()
1516
1510
 Lines 1561-1571    Link Here 
1561
            #
1555
            #
1562
            if job.is_skip:
1556
            if job.is_skip:
1563
                f = open(xml_results_file, 'a')
1557
                f = open(xml_results_file, 'a')
1564
                f.write("<TestSuite>\n")
1558
                f.write("<Test>\n")
1565
                f.write("  <SuiteName>%s</SuiteName>\n" % job.display_name)
1559
                f.write("  <Name>%s</Name>\n" % job.display_name)
1566
                f.write('  <SuiteResult>SKIP</SuiteResult>\n')
1560
                f.write('  <Result>SKIP</Result>\n')
1567
                f.write('  <SuiteTime>Execution times not available</SuiteTime>\n')
1561
                f.write("</Test>\n")
1568
                f.write("</TestSuite>\n")
1569
                f.close()
1562
                f.close()
1570
            else:
1563
            else:
1571
                if job.returncode == 0 or job.returncode == 1 or job.returncode == 2:
1564
                if job.returncode == 0 or job.returncode == 1 or job.returncode == 2:
 Lines 1576-1595    Link Here 
1576
                    f_from.close()
1569
                    f_from.close()
1577
                else:
1570
                else:
1578
                    f = open(xml_results_file, 'a')
1571
                    f = open(xml_results_file, 'a')
1579
                    f.write("<TestSuite>\n")
1572
                    f.write("<Test>\n")
1580
                    f.write("  <SuiteName>%s</SuiteName>\n" % job.display_name)
1573
                    f.write("  <Name>%s</Name>\n" % job.display_name)
1581
                    f.write('  <SuiteResult>CRASH</SuiteResult>\n')
1574
                    f.write('  <Result>CRASH</Suite>\n')
1582
                    f.write('  <SuiteTime>Execution times not available</SuiteTime>\n')
1575
                    f.write("</Test>\n")
1583
                    f.write("</TestSuite>\n")
1584
                    f.close()
1576
                    f.close()
1585
1577
1586
                    if job.returncode == 2:
1578
                    if job.returncode == 2:
1587
                        f = open(xml_results_file, 'a')
1579
                        f = open(xml_results_file, 'a')
1588
                        f.write("<TestSuite>\n")
1580
                        f.write("<Test>\n")
1589
                        f.write("  <SuiteName>%s</SuiteName>\n" % job.display_name)
1581
                        f.write("  <Name>%s</Name>\n" % job.display_name)
1590
                        f.write('  <SuiteResult>VALGR</SuiteResult>\n')
1582
                        f.write('  <Result>VALGR</Result>\n')
1591
                        f.write('  <SuiteTime>Execution times not available</SuiteTime>\n')
1583
                        f.write("</Test>\n")
1592
                        f.write("</TestSuite>\n")
1593
                        f.close()
1584
                        f.close()
1594
1585
1595
    #
1586
    #
 Lines 1607-1613    Link Here 
1607
    # document
1598
    # document
1608
    #
1599
    #
1609
    f = open(xml_results_file, 'a')
1600
    f = open(xml_results_file, 'a')
1610
    f.write('</TestResults>\n')
1601
    f.write('</Results>\n')
1611
    f.close()
1602
    f.close()
1612
1603
1613
    #
1604
    #
 Lines 1669-1674    Link Here 
1669
                      metavar="EXAMPLE",
1660
                      metavar="EXAMPLE",
1670
                      help="specify a single example to run (with relative path)")
1661
                      help="specify a single example to run (with relative path)")
1671
1662
1663
    parser.add_option("-u", "--update-data", action="store_true", dest="update_data", default=False,
1664
                      help="If examples use reference data files, get them to re-generate them")
1665
1672
    parser.add_option("-g", "--grind", action="store_true", dest="valgrind", default=False,
1666
    parser.add_option("-g", "--grind", action="store_true", dest="valgrind", default=False,
1673
                      help="run the test suites and examples using valgrind")
1667
                      help="run the test suites and examples using valgrind")
1674
1668
(-)a/utils/test-runner.cc (-449 / +2 lines)
 Lines 17-471    Link Here 
17
 */
17
 */
18
18
19
#include "ns3/test.h"
19
#include "ns3/test.h"
20
#include "ns3/assert.h"
21
#include "ns3/abort.h"
22
20
23
#include <iostream>
21
int main (int argc, char *argv[])
24
#include <fstream>
25
#include <string>
26
#include <stdlib.h>
27
#include <stdio.h>
28
#include <time.h>
29
#include <sys/types.h>
30
#include <sys/stat.h>
31
#include <dirent.h>
32
#include <string.h>
33
34
extern bool gBreakOnFailure;
35
36
using namespace ns3;
37
38
//
39
// Create a temporary directory for use by test programs.  This is not a 
40
// foolproof thing, but a reasonably good way to get a throwaway directory
41
// while running tests in a debugger.
42
//  
43
std::string
44
TempDir (void)
45
{
22
{
46
  char *path = NULL;
23
  return ns3::TestRunner::Run (argc, argv);
47
48
  path = getenv ("TMP");
49
  if (path == NULL)
50
    {
51
      path = getenv ("TEMP");
52
      if (path == NULL)
53
        {
54
          path = const_cast<char *> ("/tmp");
55
        }
56
    }
57
58
  //
59
  // Just in case the user wants to go back and find the output, we give
60
  // a hint as to which dir we created by including a time hint.
61
  //
62
  time_t now = time (NULL);
63
  struct tm *tm_now = localtime (&now);
64
  
65
  //
66
  // But we also randomize the name in case there are multiple users doing
67
  // this at the same time
68
  //
69
  srand (time (0));
70
  long int n = rand ();
71
72
  //
73
  // The final path to the directory is going to look something like
74
  // 
75
  //   /tmp/ns3-14.30.29.32767
76
  //
77
  // The first segment comes from one of the temporary directory env 
78
  // variables or /tmp if not found.  The directory name starts with an
79
  // identifier telling folks who is making all of the temp directories
80
  // and then the local time (in this case 14.30.29 -- which is 2:30 and
81
  // 29 seconds PM).
82
  //
83
  char dirname[1024];
84
  snprintf (dirname, sizeof(dirname),  "%s/ns-3.%d.%d.%d.%ld", path, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec, n);
85
86
#if (defined(_WIN32) || defined(_WIN64)) && !defined(__CYGWIN__)
87
  if(mkdir(dirname) == 0)
88
#else
89
  if (mkdir (dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0)
90
#endif
91
    {
92
      return dirname;
93
    } 
94
  else
95
    {
96
      return "";
97
    }
98
}
24
}
99
100
//
101
// Test suites may need to figure out where their source directory is in order
102
// to find test vectors.  To do that they will need to know  where the base 
103
// directory of the distribution is (the directory in which "src" is found).
104
// It is painful for a user debugging test suites to always provide that dir
105
// so we try and find it in the current directory tree.
106
//
107
std::string
108
BaseDir (void)
109
{
110
  //
111
  // Get an absolute path to the current working directory.  Following code
112
  // depends on the leading '/'
113
  //
114
  char pathbuf[PATH_MAX];
115
  if (getcwd (pathbuf, sizeof(pathbuf)) == NULL)
116
    {
117
      NS_ABORT_MSG ("Basedir():  unable to getcwd()");
118
    }
119
120
  //
121
  // Walk up the directory tree looking for a directory that has files that
122
  // indicate it is the base of an ns-3 distribution.  We use VERSION and
123
  // LICENSE which have been there from the beginning of time.
124
  //
125
  for (;;)
126
    {
127
      bool haveVersion = false;
128
      bool haveLicense = false;
129
130
      //
131
      // Open the directory file for the current directory and loop through
132
      // the directory entries.
133
      //
134
      DIR *dp = opendir (pathbuf);
135
      if (dp != NULL)
136
        {
137
          while (struct dirent *de = readdir (dp))
138
            {
139
              if (strcmp (de->d_name, "VERSION") == 0)
140
                {
141
                  haveVersion = true;
142
                }
143
144
              if (strcmp (de->d_name, "LICENSE") == 0)
145
                {
146
                  haveLicense = true;
147
                }
148
            }
149
        }
150
      closedir (dp);
151
152
      //
153
      // If there's a file named VERSION and a file named LICENSE in this
154
      // directory, we assume it's our base directory.
155
      //
156
      if (haveVersion && haveLicense)
157
        {
158
          return pathbuf;
159
        }
160
161
      //
162
      // Strip off the last segment of the current directory.
163
      //
164
      char *last = strrchr (pathbuf, '/');
165
      NS_ASSERT_MSG (last, "No \"/\" found in absolute path ???");
166
      *last = '\0';
167
168
      if (strlen(pathbuf) == 0)
169
        {
170
          return "";
171
        }
172
    }
173
174
  //
175
  // Quiet the compiler.
176
  //
177
  return "";
178
}
179
180
//
181
// Run one of the test suites.  Returns an integer with the boolean sense of
182
// "an error has occurred."  That is, 0 == false -> no error; 1 == true -> an
183
// error occurred.
184
//
185
int 
186
main (int argc, char *argv[])
187
{
188
  bool doVerbose = false;
189
  bool doList = false;
190
  bool doMultiple = false;
191
  bool doHelp = false;
192
  bool doSuite = false;
193
  bool doKinds = false;
194
195
  gBreakOnFailure = false;
196
197
  bool haveBasedir = false;
198
  bool haveTempdir = false;
199
  bool haveType = false;
200
201
  std::string suiteName;
202
  std::string basedir;
203
  std::string tempdir;
204
  std::string outfileName;
205
  std::string typeName;
206
207
208
  for (int i = 1; i < argc; ++i)
209
    {
210
      std::string arg(argv[i]);
211
212
      if (arg.find ("--assert") != std::string::npos)
213
        {
214
          gBreakOnFailure = true;
215
        }
216
217
      if (arg.find ("--basedir=") != std::string::npos)
218
        {
219
          basedir = arg.substr (arg.find_first_of ("=") + 1, 9999);
220
          haveBasedir = true;
221
        }
222
223
      if (arg.find ("--constrain=") != std::string::npos)
224
        {
225
          typeName = arg.substr (arg.find_first_of ("=") + 1, 9999);
226
          haveType = true;
227
        }
228
229
      if (arg.compare ("--help") == 0)
230
        {
231
          doHelp = true;
232
        }
233
234
      if (arg.compare ("--kinds") == 0)
235
        {
236
          doKinds = true;
237
        }
238
239
      if (arg.compare ("--list") == 0)
240
        {
241
          doList = true;
242
        }
243
244
      if (arg.compare ("--multiple") == 0)
245
        {
246
          doMultiple = true;
247
        }
248
249
      if (arg.find ("--out=") != std::string::npos)
250
        {
251
          outfileName = arg.substr (arg.find_first_of ("=") + 1, 9999);
252
        }
253
254
      if (arg.find ("--suite=") != std::string::npos)
255
        {
256
          suiteName = arg.substr (arg.find_first_of ("=") + 1, 9999);
257
          doSuite = true;
258
        }
259
260
      if (arg.find ("--tempdir=") != std::string::npos)
261
        {
262
          tempdir = arg.substr (arg.find_first_of ("=") + 1, 9999);
263
          haveTempdir = true;
264
        }
265
266
      if (arg.compare ("--verbose") == 0)
267
        {
268
          doVerbose = true;
269
        }
270
    }
271
272
  //
273
  // A help request trumps everything else.  If we have one, just print the help
274
  // and leave.
275
  //
276
  if (doHelp)
277
    {
278
      std::cout << "  --assert:               Tell tests to segfault (like assert) if an error is detected" << std::endl;
279
      std::cout << "  --basedir=dir:          Set the base directory (where to find src) to \"dir\"" << std::endl;
280
      std::cout << "  --tempdir=dir:          Set the temporary directory (where to find data files) to \"dir\"" << std::endl;
281
      std::cout << "  --constrain=test-type:  Constrain checks to test suites of type \"test-type\"" << std::endl;
282
      std::cout << "  --help:                 Print this message" << std::endl;
283
      std::cout << "  --kinds:                List all of the available kinds of tests" << std::endl;
284
      std::cout << "  --list:                 List all of the test suites (optionally constrained by test-type)" << std::endl;
285
      std::cout << "  --multiple:             Allow test suites and cases to produce multiple failures" << std::endl;
286
      std::cout << "  --out=file-name:        Set the test status output file to \"file-name\"" << std::endl;
287
      std::cout << "  --suite=suite-name:     Run the test suite named \"suite-name\"" << std::endl;
288
      std::cout << "  --verbose:              Turn on messages in the run test suites" << std::endl;
289
290
      return false;
291
    }
292
293
  //
294
  // A kinds request trumps everything remaining.  If we are asked, just 
295
  // print the list of types and leave.
296
  //
297
  if (doKinds)
298
    {
299
      //
300
      // Coming up with a string to represent a test type is completely up to
301
      // us here.  We just define the types as being a string composed of the
302
      // enum defined in test.h converted to lower case.
303
      //
304
      std::cout << "  bvt:         Build Verification Tests (to see if build completed successfully)" << std::endl;
305
      std::cout << "  core:        Run all TestSuite-based tests (exclude examples)" << std::endl;
306
      std::cout << "  example:     Examples (to see if example programs run successfully)" << std::endl;
307
      std::cout << "  performance: Performance Tests (check to see if the system is as fast as expected)" << std::endl;
308
      std::cout << "  system:      System Tests (spans modules to check integration of modules)" << std::endl;
309
      std::cout << "  unit:        Unit Tests (within modules to check basic functionality)" << std::endl;
310
311
      return false;
312
    }
313
314
  //
315
  // A list request is the first functional request.  It trumps running the
316
  // actual tests.  If we get a list request, we don't run anything, we just
317
  // do the requested list which may or may not be qualified by a typename.
318
  //
319
  if (doList)
320
    {
321
      for (uint32_t i = 0; i < TestRunner::GetNTestSuites (); ++i)
322
        {
323
          TestSuite *suite = TestRunner::GetTestSuite (i);
324
325
          //
326
          // Filter the tests listed by type if requested.  The special typeName 
327
          // "core" means any TestSuite.
328
          //
329
          if (haveType && typeName != "core")
330
            {
331
              TestSuite::TestType type = suite->GetTestType ();
332
              if (typeName == "bvt" && type != TestSuite::BVT)
333
                {
334
                  continue;
335
                }
336
337
              if (typeName == "unit" && type != TestSuite::UNIT)
338
                {
339
                  continue;
340
                }
341
342
              if (typeName == "system" && type != TestSuite::SYSTEM)
343
                {
344
                  continue;
345
                }
346
347
              if (typeName == "example" && type != TestSuite::EXAMPLE)
348
                {
349
                  continue;
350
                }
351
352
              if (typeName == "performance" && type != TestSuite::PERFORMANCE)
353
                {
354
                  continue;
355
                }
356
            }
357
358
          //
359
          // This creates a list of test suite names that can be used by the
360
          // high level test manager to get a list of all tests.  It will then
361
          // typically launch individual tests in parallel, calling back here
362
          // with a specific "suite=" to run.
363
          //
364
          std::cout << suite->GetName () << std::endl;
365
        }
366
367
      return false;
368
    }
369
370
  //
371
  // We have a lot of options possible to provide flexibility.  It can become
372
  // painful, however, to provide all of the options when debugging, and it 
373
  // turns out that not all tests require all options.  It is really helpful
374
  // to try and put together some reasonable defaults if we're not provided
375
  // them.
376
  //
377
  if (!haveTempdir)
378
    {
379
      //
380
      // No temporary directory was provided.  We don't know if the selected
381
      // test or tests will need one, but we can cook something up.  The 
382
      // tmpnam function has its own set of problems, so we'll just do our 
383
      // own thing.
384
      //
385
      tempdir = TempDir ();
386
      if (tempdir.size ()) 
387
        {
388
          std::cout << "Temporary directory not provided.  Using \"" << tempdir << "\"" << std::endl;
389
          haveTempdir = true;
390
        }
391
      else
392
        {
393
          std::cout << "Temporary directory not provided and unable to create one." << std::endl;
394
          return true;
395
        }
396
    }
397
398
  if (haveBasedir == false)
399
    {
400
      //
401
      // No basedir was provided.  If we don't have it, we can try and find it 
402
      // in the current directory tree.
403
      //
404
      basedir = BaseDir ();
405
      if (basedir.size ()) 
406
        {
407
          std::cout << "Base directory not provided.  Using \"" << basedir << "\"" << std::endl;
408
          haveBasedir = true;
409
        }
410
      else
411
        {
412
          std::cout << "Base directory not provided and unable to find one." << std::endl;
413
          return true;
414
        }
415
    }
416
417
  //
418
  // If given an output file, we just append the output of each test suite 
419
  // we're asked to run to the end of that file.  We need to append since the
420
  // higher level test runner may be just running a number of tests back to 
421
  // back.  We leave it up to that code to decide how to deal with possible
422
  // parallel operation -- we just append to a file here.  If no output file
423
  // is specified, we don't do any output and just return the sense of error
424
  // given by the test.
425
  //
426
  std::ofstream *pofs = 0;
427
  std::ofstream ofs;
428
429
  if (!outfileName.empty ())
430
    {
431
      ofs.open (outfileName.c_str (), std::fstream::out | std::fstream::app);
432
      pofs = &ofs;
433
    }
434
435
  //
436
  // If we have a specified test suite to run, then we only run that suite.
437
  // The default case is to "run everything.  We don't expect this to be done
438
  // much since typically higher level code will be running suites in parallel
439
  // but we'll do it if asked.
440
  //
441
  bool result = false;
442
  bool suiteRan = false;
443
444
  for (uint32_t i = 0; i < TestRunner::GetNTestSuites (); ++i)
445
    {
446
      TestSuite *testSuite = TestRunner::GetTestSuite (i);
447
      if (doSuite == false || (doSuite == true && suiteName == testSuite->GetName ()))
448
        {
449
          testSuite->SetBaseDir (basedir);
450
          testSuite->SetTempDir (tempdir);
451
          testSuite->SetStream (pofs);
452
          testSuite->SetVerbose (doVerbose);
453
          testSuite->SetContinueOnFailure (doMultiple);
454
          result |= testSuite->Run ();
455
          suiteRan = true;
456
        }
457
    }
458
459
  ofs.close();
460
461
  //
462
  // If we couldn't figure out how to run at least one test, then return an error
463
  //
464
  if (suiteRan == false)
465
    {
466
      std::cout << "Unable to find a test to run (constraints too severe or test not found)" << std::endl;
467
      return true;
468
    }
469
470
  return result;
471
}

Return to bug 1001