Fix timestamp-related Decider() examples by using Object() instead of
[scons.git] / runtest.py
index f99f5a1b4ad5c2831dd59974fea7e12f59df9b42..a4dcee416078e921ce7e9d4ef4ede2364c19997c 100644 (file)
@@ -89,7 +89,6 @@ import getopt
 import glob
 import os
 import os.path
-import popen2
 import re
 import stat
 import string
@@ -165,7 +164,9 @@ opts, args = getopt.getopt(sys.argv[1:], "ab:df:hlno:P:p:qv:Xx:t",
                             ['all', 'aegis', 'baseline=', 'builddir=',
                              'debug', 'file=', 'help',
                              'list', 'no-exec', 'noqmtest', 'output=',
-                             'version=', 'exec=', 'time',
+                             'package=', 'passed', 'python=', 'qmtest',
+                             'quiet', 'sp=', 'spe=', 'time',
+                             'version=', 'exec=',
                              'verbose=', 'xml'])
 
 for o, a in opts:
@@ -207,7 +208,11 @@ for o, a in opts:
     elif o in ['-P', '--python']:
         python = a
     elif o in ['--qmtest']:
-        qmtest = 'qmtest.py'
+        if sys.platform == 'win32':
+            # typically in c:/PythonXX/Scripts
+            qmtest = 'qmtest.py'
+        else:
+            qmtest = 'qmtest'
     elif o in ['-q', '--quiet']:
         printcommand = 0
     elif o in ['--sp']:
@@ -240,7 +245,7 @@ runtest.py:  No tests were specified.
 if sys.platform in ('win32', 'cygwin'):
 
     def whereis(file):
-        pathext = [''] + string.split(os.environ['PATHEXT'])
+        pathext = [''] + string.split(os.environ['PATHEXT'], os.pathsep)
         for dir in string.split(os.environ['PATH'], os.pathsep):
             f = os.path.join(dir, file)
             for ext in pathext:
@@ -263,16 +268,25 @@ else:
                     return f
         return None
 
+# See if --qmtest or --noqmtest specified
 try:
     qmtest
 except NameError:
-    q = 'qmtest.py'
-    qmtest = whereis(q)
-    if qmtest:
-        qmtest = q
-    else:
-        sys.stderr.write('Warning:  %s not found on $PATH, assuming --noqmtest option.\n' % q)
-        sys.stderr.flush()
+    qmtest = None
+    # Old code for using QMTest by default if it's installed.
+    # We now default to not using QMTest unless explicitly asked for.
+    #for q in ['qmtest', 'qmtest.py']:
+    #    path = whereis(q)
+    #    if path:
+    #        # The name was found on $PATH; just execute the found name so
+    #        # we don't have to worry about paths containing white space.
+    #        qmtest = q
+    #        break
+    #if not qmtest:
+    #    msg = ('Warning:  found neither qmtest nor qmtest.py on $PATH;\n' +
+    #           '\tassuming --noqmtest option.\n')
+    #    sys.stderr.write(msg)
+    #    sys.stderr.flush()
 
 aegis = whereis('aegis')
 
@@ -302,6 +316,7 @@ _ws = re.compile('\s')
 def escape(s):
     if _ws.search(s):
         s = '"' + s + '"'
+    s = string.replace(s, '\\', '\\\\')
     return s
 
 # Set up lowest-common-denominator spawning of a process on both Windows
@@ -342,25 +357,42 @@ class SystemExecutor(Base):
             sys.stdout.write("Unexpected exit status %d\n" % s)
 
 try:
-    popen2.Popen3
-except AttributeError:
-    class PopenExecutor(Base):
-        def execute(self):
-            (tochild, fromchild, childerr) = os.popen3(self.command_str)
-            tochild.close()
-            self.stderr = childerr.read()
-            self.stdout = fromchild.read()
-            fromchild.close()
-            self.status = childerr.close()
-            if not self.status:
-                self.status = 0
+    import subprocess
+except ImportError:
+    import popen2
+    try:
+        popen2.Popen3
+    except AttributeError:
+        class PopenExecutor(Base):
+            def execute(self):
+                (tochild, fromchild, childerr) = os.popen3(self.command_str)
+                tochild.close()
+                self.stderr = childerr.read()
+                self.stdout = fromchild.read()
+                fromchild.close()
+                self.status = childerr.close()
+                if not self.status:
+                    self.status = 0
+                else:
+                    self.status = self.status >> 8
+    else:
+        class PopenExecutor(Base):
+            def execute(self):
+                p = popen2.Popen3(self.command_str, 1)
+                p.tochild.close()
+                self.stdout = p.fromchild.read()
+                self.stderr = p.childerr.read()
+                self.status = p.wait()
+                self.status = self.status >> 8
 else:
     class PopenExecutor(Base):
         def execute(self):
-            p = popen2.Popen3(self.command_str, 1)
-            p.tochild.close()
-            self.stdout = p.fromchild.read()
-            self.stderr = p.childerr.read()
+            p = subprocess.Popen(self.command_str,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.PIPE,
+                                 shell=True)
+            self.stdout = p.stdout.read()
+            self.stderr = p.stderr.read()
             self.status = p.wait()
 
 class Aegis(SystemExecutor):
@@ -548,6 +580,25 @@ if old_pythonpath:
 
 tests = []
 
+def find_Tests_py(tdict, dirname, names):
+    for n in filter(lambda n: n[-8:] == "Tests.py", names):
+        tdict[os.path.join(dirname, n)] = 1
+
+def find_py(tdict, dirname, names):
+    tests = filter(lambda n: n[-3:] == ".py", names)
+    try:
+        excludes = open(os.path.join(dirname,".exclude_tests")).readlines()
+    except (OSError, IOError):
+        pass
+    else:
+        for exclude in excludes:
+            exclude = string.split(exclude, '#' , 1)[0]
+            exclude = string.strip(exclude)
+            if not exclude: continue
+            tests = filter(lambda n, ex = exclude: n != ex, tests)
+    for n in tests:
+        tdict[os.path.join(dirname, n)] = 1
+
 if args:
     if spe:
         for a in args:
@@ -562,7 +613,18 @@ if args:
                         break
     else:
         for a in args:
-            tests.extend(glob.glob(a))
+            for path in glob.glob(a):
+                if os.path.isdir(path):
+                    tdict = {}
+                    if path[:3] == 'src':
+                        os.path.walk(path, find_Tests_py, tdict)
+                    elif path[:4] == 'test':
+                        os.path.walk(path, find_py, tdict)
+                    t = tdict.keys()
+                    t.sort()
+                    tests.extend(t)
+                else:
+                    tests.append(path)
 elif testlistfile:
     tests = open(testlistfile, 'r').readlines()
     tests = filter(lambda x: x[0] != '#', tests)
@@ -580,21 +642,8 @@ elif all and not qmtest:
     # by the Aegis packaging build to make sure that we're building
     # things correctly.)
     tdict = {}
-
-    def find_Tests_py(tdict, dirname, names):
-        for n in filter(lambda n: n[-8:] == "Tests.py", names):
-            t = os.path.join(dirname, n)
-            if not tdict.has_key(t):
-                tdict[t] = 1
     os.path.walk('src', find_Tests_py, tdict)
-
-    def find_py(tdict, dirname, names):
-        for n in filter(lambda n: n[-3:] == ".py", names):
-            t = os.path.join(dirname, n)
-            if not tdict.has_key(t):
-                tdict[t] = 1
     os.path.walk('test', find_py, tdict)
-
     if format == '--aegis' and aegis:
         cmd = "aegis -list -unf pf 2>/dev/null"
         for line in os.popen(cmd, "r").readlines():
@@ -682,10 +731,11 @@ class Unbuffered:
         return getattr(self.file, attr)
 
 sys.stdout = Unbuffered(sys.stdout)
+sys.stderr = Unbuffered(sys.stderr)
 
 if list_only:
     for t in tests:
-        sys.stdout.write(t.abspath + "\n")
+        sys.stdout.write(t.path + "\n")
     sys.exit(0)
 
 #
@@ -714,7 +764,7 @@ for t in tests:
     t.command_args = [python, '-tt']
     if debug:
         t.command_args.append(debug)
-    t.command_args.append(t.abspath)
+    t.command_args.append(t.path)
     t.command_str = string.join(map(escape, t.command_args), " ")
     if printcommand:
         sys.stdout.write(t.command_str + "\n")
@@ -776,3 +826,9 @@ elif len(no_result):
     sys.exit(2)
 else:
     sys.exit(0)
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: