make life easier for folks running test-runner directly
authorCraig Dowell <craigdo@ee.washington.edu>
Tue, 13 Apr 2010 18:41:11 -0700
changeset 6194 5f8e99c4c456
parent 6193 808bcfa200f4
child 6195 cc5b5294031f
child 6200 2bf2700b6e67
make life easier for folks running test-runner directly
utils/test-runner.cc
--- 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;
     }