enable debugger breaks in test-runner and document changes
authorCraig Dowell <craigdo@ee.washington.edu>
Thu, 15 Apr 2010 16:37:57 -0700
changeset 6204 db1a9442b29f
parent 6203 1204777b0bcf
child 6205 a3ea6338c23e
enable debugger breaks in test-runner and document changes
doc/testing/testing-framework.texi
src/core/test.cc
src/core/test.h
utils/test-runner.cc
--- a/doc/testing/testing-framework.texi	Thu Apr 15 15:11:49 2010 -0700
+++ b/doc/testing/testing-framework.texi	Thu Apr 15 16:37:57 2010 -0700
@@ -487,6 +487,7 @@
   Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
   Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
   'build' finished successfully (0.353s)
+  --assert:               Tell tests to segfault (like assert) if an error is detected
   --basedir=dir:          Set the base directory (where to find src) to ``dir''
   --constrain=test-type:  Constrain checks to test suites of type ``test-type''
   --help:                 Print this message
@@ -506,24 +507,82 @@
 as if they were to present a unified testing environment, but they are really
 completely different and not to be found here.
 
-One new option that appears here is the @code{--basedir} option.  It turns out
-that the tests may need to reference the source directory of the @code{ns-3} 
+The first new option that appears here, but not in test.py is the @code{--assert}
+option.  This option is useful when debugging a test case when running under a 
+debugger like @code{gdb}.  When selected, this option tells the underlying
+test case to cause a segmentation violation if an error is detected.  This has
+the nice side-effect of causing program execution to stop (break into the 
+debugger) when an error is detected.  If you are using gdb, you could use this
+option something like,
+
+@smallformat
+@verbatim
+  ./waf shell
+  cd build/debug/utils
+  gdb test-runner
+  run --suite=global-value --assert
+@end verbatim
+@end smallformat
+
+If an error is then found in the global-value test suite, a segfault would be 
+generated and the (source level) debugger would stop at the @code{NS_TEST_ASSERT_MSG}
+that detected the error.
+
+Another new option that appears here is the @code{--basedir} option.  It turns out
+that some tests may need to reference the source directory of the @code{ns-3} 
 distribution to find local data, so a base directory is always required to run
-a test.  To run one of the tests directly from the test-runner, you will need
-to specify the test suite to run along with the base directory.  So you could do,
+a test.
+
+If you run a test from test.py, the Python program will provide the basedir option
+for you.  To run one of the tests directly from the test-runner using @code{waf},
+ you will need to specify the test suite to run along with the base directory.  So 
+you could use the shell and do,
 
 @verbatim
   ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object"
 @end verbatim
 
-Note the ``backward'' quotation marks on the @code{pwd} command.  This will run
-the @code{pcap-file-object} test quietly.  The only indication that
-you will get that the test passed is the @emph{absence} of a message from 
-@code{waf} saying that the program returned something other than a zero 
-exit code.  To get some output from the test, you need to specify an output
-file to which the tests will write their XML status using the @code{--out}
-option.  You need to be careful interpreting the results because the test 
-suites will @emph{append} results onto this file.  Try,
+Note the ``backward'' quotation marks on the @code{pwd} command.  
+
+If you are running the test suite out of a debugger, it can be quite painful to
+remember and constantly type the absolute path of the distribution base directory.
+Because of this, if you omit the basedir, the test-runner will try to figure one
+out for you.  It begins in the current working directory and walks up the 
+directory tree looking for a directory file with files named ``VERSION'' and
+``LICENSE.''  If it finds one, it assumes that must be the basedir and provides
+it for you.
+
+Similarly, many test suites need to write temporary files (such as pcap files)
+in the process of running the tests.  The tests then need a temporary directory
+to write to.  The Python test utility (test.py) will provide a temporary file
+automatically, but if run stand-alone this temporary directory must be provided.
+Just as in the basedir case, it can be annoying to continually have to provide
+a @code{--tempdir}, so the test runner will figure one out for you if you don't
+provide one.  It first looks for environment variables named @code{TMP} and 
+@code{TEMP} and uses those.  If neither @code{TMP} nor @code{TEMP} are defined
+it picks @code{/tmp}.  The code then tacks on the time (hh.mm.ss} followed by
+a large randome number and creates a directory of that name to be used as the
+temporary directory.  Temporary files then go into a directory that will be
+named something like,
+
+@smallformat
+@verbatim
+  /tmp/10.25.37.61537845
+@end verbatim
+@end smallformat
+
+The time is provided as a hint so that you can relatively easily reconstruct
+what directory was used if you need to go back and look at the files that were
+placed in that directory.
+
+When you run a test suite using the test-runner it will run the test quietly
+by default.  The only indication that you will get that the test passed is 
+the @emph{absence} of a message from @code{waf} saying that the program 
+returned something other than a zero exit code.  To get some output from the
+test, you need to specify an output file to which the tests will write their 
+XML status using the @code{--out} option.  You need to be careful interpreting
+ the results because the test suites will @emph{append} results onto this file.
+Try,
 
 @smallformat
 @verbatim
--- a/src/core/test.cc	Thu Apr 15 15:11:49 2010 -0700
+++ b/src/core/test.cc	Thu Apr 15 16:37:57 2010 -0700
@@ -21,9 +21,10 @@
 #include "abort.h"
 #include <math.h>
 
+bool gBreakOnFailure = false;
+
 namespace ns3 {
 
-
 //
 // XML files have restrictions on certain characters that may be present in
 // data.  We need to replace these characters with their alternate 
--- a/src/core/test.h	Thu Apr 15 15:11:49 2010 -0700
+++ b/src/core/test.h	Thu Apr 15 16:37:57 2010 -0700
@@ -30,6 +30,7 @@
 
 #include "ns3/system-wall-clock-ms.h"
 
+extern bool gBreakOnFailure;
 
 // 
 // Note on below macros:
@@ -67,6 +68,7 @@
   do {                                                                                                  \
     if (!((actual) == (limit)))                                                                         \
       {                                                                                                 \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                           \
         std::ostringstream msgStream;                                                                   \
         msgStream << msg;                                                                               \
         std::ostringstream actualStream;                                                                \
@@ -121,6 +123,7 @@
   do {                                                                                                  \
     if (!((actual) == (limit)))                                                                         \
       {                                                                                                 \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                           \
         std::ostringstream msgStream;                                                                   \
         msgStream << msg;                                                                               \
         std::ostringstream actualStream;                                                                \
@@ -173,6 +176,7 @@
   do {                                                                                                                \
     if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol))                                                     \
       {                                                                                                               \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                                         \
         std::ostringstream msgStream;                                                                                 \
         msgStream << msg;                                                                                             \
         std::ostringstream actualStream;                                                                              \
@@ -251,6 +255,7 @@
   do {                                                                                                                \
     if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol))                                                     \
       {                                                                                                               \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                                         \
         std::ostringstream msgStream;                                                                                 \
         msgStream << msg;                                                                                             \
         std::ostringstream actualStream;                                                                              \
@@ -326,6 +331,7 @@
   do {                                                                                                  \
     if (!((actual) != (limit)))                                                                         \
       {                                                                                                 \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                           \
         std::ostringstream msgStream;                                                                   \
         msgStream << msg;                                                                               \
         std::ostringstream actualStream;                                                                \
@@ -379,6 +385,7 @@
   do {                                                                                                  \
     if (!((actual) != (limit)))                                                                         \
       {                                                                                                 \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                           \
         std::ostringstream msgStream;                                                                   \
         msgStream << msg;                                                                               \
         std::ostringstream actualStream;                                                                \
@@ -429,6 +436,7 @@
   do {                                                                                                   \
     if (!((actual) < (limit)))                                                                           \
       {                                                                                                  \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                            \
         std::ostringstream msgStream;                                                                    \
         msgStream << msg;                                                                                \
         std::ostringstream actualStream;                                                                 \
@@ -472,6 +480,7 @@
   do {                                                                                                   \
     if (!((actual) < (limit)))                                                                           \
       {                                                                                                  \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                            \
         std::ostringstream msgStream;                                                                    \
         msgStream << msg;                                                                                \
         std::ostringstream actualStream;                                                                 \
@@ -511,6 +520,7 @@
   do {                                                                                                   \
     if (!((actual) > (limit)))                                                                           \
       {                                                                                                  \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                            \
         std::ostringstream msgStream;                                                                    \
         msgStream << msg;                                                                                \
         std::ostringstream actualStream;                                                                 \
@@ -554,6 +564,7 @@
   do {                                                                                                   \
     if (!((actual) > (limit)))                                                                           \
       {                                                                                                  \
+        if (gBreakOnFailure) {*(int *)0 = 0;}                                                            \
         std::ostringstream msgStream;                                                                    \
         msgStream << msg;                                                                                \
         std::ostringstream actualStream;                                                                 \
--- a/utils/test-runner.cc	Thu Apr 15 15:11:49 2010 -0700
+++ b/utils/test-runner.cc	Thu Apr 15 16:37:57 2010 -0700
@@ -30,6 +30,8 @@
 #include <dirent.h>
 #include <string.h>
 
+extern bool gBreakOnFailure;
+
 using namespace ns3;
 
 //
@@ -172,6 +174,8 @@
   bool doSuite = false;
   bool doKinds = false;
 
+  gBreakOnFailure = false;
+
   bool haveBasedir = false;
   bool haveTempdir = false;
   bool haveOutfile = false;
@@ -183,10 +187,16 @@
   std::string outfileName;
   std::string typeName;
 
+
   for (int i = 1; i < argc; ++i)
     {
       std::string arg(argv[i]);
 
+      if (arg.find ("--assert") != std::string::npos)
+        {
+          gBreakOnFailure = true;
+        }
+
       if (arg.find ("--basedir=") != std::string::npos)
         {
           basedir = arg.substr (arg.find_first_of ("=") + 1, 9999);
@@ -249,6 +259,7 @@
   //
   if (doHelp)
     {
+      std::cout << "  --assert:               Tell tests to segfault (like assert) if an error is detected" << std::endl;
       std::cout << "  --basedir=dir:          Set the base directory (where to find src) to \"dir\"" << std::endl;
       std::cout << "  --tempdir=dir:          Set the temporary directory (where to find data files) to \"dir\"" << std::endl;
       std::cout << "  --constrain=test-type:  Constrain checks to test suites of type \"test-type\"" << std::endl;