--- a/utils/test-runner.cc Mon Apr 12 21:42:53 2010 -0700
+++ b/utils/test-runner.cc Tue Apr 13 18:41:11 2010 -0700
@@ -17,14 +17,147 @@
*/
#include "ns3/test.h"
+#include "ns3/assert.h"
#include <iostream>
#include <fstream>
#include <string>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <string.h>
using namespace ns3;
//
+// Create a temporary directory for use by test programs. This is not a
+// foolproof thing, but a reasonably good way to get a throwaway directory
+// while running tests in a debugger.
+//
+std::string
+TempDir (void)
+{
+ char *path = NULL;
+
+ path = getenv ("TMP");
+ if (path == NULL)
+ {
+ path = getenv ("TEMP");
+ if (path == NULL)
+ {
+ path = const_cast<char *> ("/tmp");
+ }
+ }
+
+ //
+ // Just in case the user wants to go back and find the output, we give
+ // a hint as to which dir we created by including a time hint.
+ //
+ time_t now = time (NULL);
+ struct tm *tm_now = localtime (&now);
+
+ //
+ // But we also randomize the name in case there are multiple users doing
+ // this at the same time
+ //
+ srandom (time (0));
+ long int n = random ();
+
+ //
+ // The final path to the directory is going to look something like
+ //
+ // /tmp/14.30.29.32767
+ //
+ // The first segment comes from one of the temporary directory env
+ // variables or /tmp if not found. The directory name starts with the
+ // local time (in this case 14.30.29 -- which is 2:30 and 29 seconds PM).
+ //
+ char dirname[1024];
+ snprintf (dirname, sizeof(dirname), "%s/%d.%d.%d.%ld", path, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec, n);
+
+ if (mkdir (dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0)
+ {
+ return dirname;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+std::string
+BaseDir (void)
+{
+ //
+ // Get an absolute path to the current working directory. Following code
+ // depends on the leading '/'
+ //
+ char pathbuf[PATH_MAX];
+ getcwd (pathbuf, sizeof(pathbuf));
+
+ //
+ // Walk up the directory tree looking for a directory that has files that
+ // indicate it is the base of an ns-3 distribution. We use VERSION and
+ // LICENSE which have been there from the beginning of time.
+ //
+ for (;;)
+ {
+ bool haveVersion = false;
+ bool haveLicense = false;
+
+ //
+ // Open the directory file for the current directory and loop through
+ // the directory entries.
+ //
+ DIR *dp = opendir (pathbuf);
+ if (dp != NULL)
+ {
+ while (struct dirent *de = readdir (dp))
+ {
+ if (strcmp (de->d_name, "VERSION") == 0)
+ {
+ haveVersion = true;
+ }
+
+ if (strcmp (de->d_name, "LICENSE") == 0)
+ {
+ haveLicense = true;
+ }
+ }
+ }
+
+ //
+ // If there's a file named VERSION and a file named LICENSE in this
+ // directory, we assume it's our base directory.
+ //
+ if (haveVersion && haveLicense)
+ {
+ return pathbuf;
+ }
+
+ //
+ // Strip off the last segment of the current directory.
+ //
+ char *last = strrchr (pathbuf, '/');
+ NS_ASSERT_MSG (last, "No \"/\" found in absolute path ???");
+ *last = '\0';
+
+ if (strlen(pathbuf) == 0)
+ {
+ return "";
+ }
+ }
+
+ //
+ // Quiet the compiler.
+ //
+ return "";
+}
+
+//
// Run one of the test suites. Returns an integer with the boolean sense of
// "an error has occurred." That is, 0 == false -> no error; 1 == true -> an
// error occurred.
@@ -208,19 +341,53 @@
}
//
- // If we haven't been asked to run a test suite, we are just going to happily
- // try and run everything. Test suites are possibly going to need to figure
- // out where there source directory is, and to do that they will need to know
- // where the base directory of the distribution is (the directory in which
- // "src" is found). We could try and run without it, but when it is needed,
- // the test will fail with an assertion. So to be safe, we require a basedir
- // to proceed.
+ // We have a lot of options possible to provide flexibility. It can become
+ // painful, however, to provide all of the options when debugging, and it
+ // turns out that not all tests require all options. It is really helpful
+ // to try and put together some reasonable defaults if we're not provided
+ // them.
//
+ if (!haveTempdir)
+ {
+ //
+ // No temporary directory was provided. We don't know if the selected
+ // test or tests will need one, but we can cook something up. The
+ // tmpnam function has its own set of problems, so we'll just do our
+ // own thing.
+ //
+ tempdir = TempDir ();
+ if (tempdir.size ())
+ {
+ std::cout << "Temporary directory not provided. Using \"" << tempdir << "\"" << std::endl;
+ haveTempdir = true;
+ }
+ else
+ {
+ std::cout << "Temporary directory not provided and unable to create one." << std::endl;
+ return true;
+ }
+ }
if (haveBasedir == false)
{
- std::cout << "Must specify a base directory to run tests (use --basedir option)" << std::endl;
- return true;
+ //
+ // Test suites are possibly going to need to figure out where their
+ // source directory is, and to do that they will need to know where
+ // the base directory of the distribution is (the directory in which
+ // "src" is found). If we don't have it, we can try and find it in
+ // the current directory tree.
+ //
+ basedir = BaseDir ();
+ if (basedir.size ())
+ {
+ std::cout << "Base directory not provided. Using \"" << basedir << "\"" << std::endl;
+ haveBasedir = true;
+ }
+ else
+ {
+ std::cout << "Base directory not provided and unable to find one." << std::endl;
+ return true;
+ }
}
//
@@ -272,6 +439,7 @@
//
if (suiteRan == false)
{
+ std::cout << "Unable to find a test to run (constraints too severe or test not found)" << std::endl;
return true;
}