changeset 4225:339cf8d4904d

Made mx.run work properly when stderr is redirected to stdout. Made outputparser redirect stderr to stdout. Added copyright headers to outputparser.py and sanitycheck.py. Reverted class path construction in mx.build() to use includeSelf=True to fix regression when running 'mx build -c'.
author Doug Simon <doug.simon@oracle.com>
date Thu, 05 Jan 2012 11:31:46 +0100
parents 26336f60ec7a
children e03ff10d4bfc
files mx/commands.py mx/outputparser.py mx/sanitycheck.py mxtool/mx.py
diffstat 4 files changed, 77 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/mx/commands.py	Wed Jan 04 23:34:15 2012 +0100
+++ b/mx/commands.py	Thu Jan 05 11:31:46 2012 +0100
@@ -1,5 +1,5 @@
 #
-# commands.py - the default commands available to gl.py
+# commands.py - the GraalVM specific commands
 #
 # ----------------------------------------------------------------------------------------------------
 #
--- a/mx/outputparser.py	Wed Jan 04 23:34:15 2012 +0100
+++ b/mx/outputparser.py	Thu Jan 05 11:31:46 2012 +0100
@@ -1,5 +1,31 @@
+# ----------------------------------------------------------------------------------------------------
+#
+# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+# ----------------------------------------------------------------------------------------------------
+
 import mx
 import commands
+import subprocess
 
 class OutputParser:
     
@@ -27,7 +53,7 @@
             else :
                 mx.log( line.rstrip())
         
-        retcode = commands.vm(cmd, vm, nonZeroIsFatal=self.nonZeroIsFatal, out=parseLine, err=parseLine, cwd=cwd, vmbuild=vmbuild)
+        retcode = commands.vm(cmd, vm, nonZeroIsFatal=self.nonZeroIsFatal, out=parseLine, err=subprocess.STDOUT, cwd=cwd, vmbuild=vmbuild)
         return {'parsed' : ret, 'retcode' : retcode}
 
 class Matcher:
@@ -50,7 +76,7 @@
     def parsestr(self, match, key):
         if isinstance(key, tuple):
             if len(key) != 2:
-                raise Exception('Tuple arguments must have a lenght of 2')
+                raise Exception('Tuple arguments must have a length of 2')
             tup1, tup2 = key
             # check if key is a function
             if hasattr(tup1, '__call__'):
--- a/mx/sanitycheck.py	Wed Jan 04 23:34:15 2012 +0100
+++ b/mx/sanitycheck.py	Thu Jan 05 11:31:46 2012 +0100
@@ -1,3 +1,28 @@
+# ----------------------------------------------------------------------------------------------------
+#
+# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+# ----------------------------------------------------------------------------------------------------
+
 from outputparser import OutputParser, Matcher
 import re
 import mx
@@ -62,23 +87,29 @@
     tests.append(Test("Bootstrap", "Bootstrap-bigHeap", ['-version'], succesREs=[time], scoreMatchers=[scoreMatcher], vmOpts=['-Xms2g']))
     return tests
 
+"""
+Encapsulates a single program that is a sanity test and/or a benchmark.
+"""
 class Test:
-    def __init__(self, name, group, cmd, succesREs=[], failureREs=[], scoreMatchers=[], vmOpts=[]):
+    def __init__(self, name, group, cmd, successREs=[], failureREs=[], scoreMatchers=[], vmOpts=[]):
         self.name = name
         self.group = group
-        self.succesREs = succesREs
+        self.successREs = successREs
         self.failureREs = failureREs
         self.scoreMatchers = scoreMatchers
         self.vmOpts = vmOpts
         self.cmd = cmd
     
     def test(self, vm, cwd=None, opts=[], vmbuild=None):
+        """
+        Run this program as a sanity test.
+        """
         parser = OutputParser(nonZeroIsFatal = False)
         jvmError = re.compile(r"(?P<jvmerror>([A-Z]:|/).*[/\\]hs_err_pid[0-9]+\.log)")
         parser.addMatcher(Matcher(jvmError, {'const:jvmError' : 'jvmerror'}))
         
-        for succesRE in self.succesREs:
-            parser.addMatcher(Matcher(succesRE, {'const:passed' : 'const:1'}))
+        for successRE in self.successREs:
+            parser.addMatcher(Matcher(successRE, {'const:passed' : 'const:1'}))
         for failureRE in self.failureREs:
             parser.addMatcher(Matcher(failureRE, {'const:failed' : 'const:1'}))
         
@@ -104,6 +135,9 @@
         return result['retcode'] is 0 and parsed.has_key('passed') and parsed['passed'] is '1'
     
     def bench(self, vm, cwd=None, opts=[], vmbuild=None):
+        """
+        Run this program as a benchmark.
+        """
         parser = OutputParser(nonZeroIsFatal = False)
         
         for scoreMatcher in self.scoreMatchers:
--- a/mxtool/mx.py	Wed Jan 04 23:34:15 2012 +0100
+++ b/mxtool/mx.py	Thu Jan 05 11:31:46 2012 +0100
@@ -535,8 +535,8 @@
     Run a command in a subprocess, wait for it to complete and return the exit status of the process.
     If the exit status is non-zero and `nonZeroIsFatal` is true, then mx is exited with
     the same exit status.
-    Each line of the standard output and error streams of the subprocess are redirected to the
-    provided out and err functions if they are not None.
+    Each line of the standard output and error streams of the subprocess are redirected to
+    out and err if they are callable objects.
     """
     
     assert isinstance(args, types.ListType), "'args' must be a list: " + str(args)
@@ -550,19 +550,21 @@
         timeout = _opts.timeout
     
     try:
-        if out is None and err is None and timeout is None:
+        if not callable(out) and not callable(err) and timeout is None:
             retcode = subprocess.call(args, cwd=cwd)
         else:
             def redirect(stream, f):
                 for line in iter(stream.readline, ''):
                     f(line)
                 stream.close()
-            p = subprocess.Popen(args, cwd=cwd, stdout=None if out is None else subprocess.PIPE, stderr=None if err is None else subprocess.PIPE)
-            if out is not None:
+            stdout=out if not callable(out) else subprocess.PIPE
+            stderr=err if not callable(err) else subprocess.PIPE
+            p = subprocess.Popen(args, cwd=cwd, stdout=stdout, stderr=stderr)
+            if callable(out):
                 t = Thread(target=redirect, args=(p.stdout, out))
                 t.daemon = True # thread dies with the program
                 t.start()
-            if err is not None:
+            if callable(err):
                 t = Thread(target=redirect, args=(p.stderr, err))
                 t.daemon = True # thread dies with the program
                 t.start()
@@ -833,7 +835,7 @@
         else:
             os.mkdir(outputDir)
 
-        cp = classpath(p.name, includeSelf=False)
+        cp = classpath(p.name, includeSelf=True)
         sourceDirs = p.source_dirs()
         mustBuild = args.force
         if not mustBuild:
@@ -885,7 +887,7 @@
                                 self.c = 0
                             
                             def eat(self, line):
-                                if 'proprietary API':
+                                if 'proprietary API' in line:
                                     self.c = 2
                                 elif self.c != 0:
                                     self.c -= 1