--- 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;