diff mx.graal/mx_graal.py @ 22020:36a7ec14279d

moved unit test support from mx_graal.py to mx.py
author Doug Simon <doug.simon@oracle.com>
date Thu, 18 Jun 2015 23:06:11 +0200
parents 07cfd3d7072b
children c4205df4f3e2
line wrap: on
line diff
--- a/mx.graal/mx_graal.py	Wed Jun 17 15:31:28 2015 +0200
+++ b/mx.graal/mx_graal.py	Thu Jun 18 23:06:11 2015 +0200
@@ -28,14 +28,14 @@
 
 import os, stat, errno, sys, shutil, zipfile, tarfile, tempfile, re, time, datetime, platform, subprocess, StringIO, socket
 from os.path import join, exists, dirname, basename
-from argparse import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER
+from argparse import ArgumentParser, REMAINDER
 from outputparser import OutputParser, ValuesMatcher
 import mx
+import mx_unittest
 import xml.dom.minidom
 import sanitycheck
 import itertools
 import json, textwrap
-import fnmatch
 import mx_graal_makefile
 
 _suite = mx.suite('graal')
@@ -318,7 +318,7 @@
 
 def _run_benchmark(args, availableBenchmarks, runBenchmark):
 
-    vmOpts, benchmarksAndOptions = _extract_VM_args(args, useDoubleDash=availableBenchmarks is None)
+    vmOpts, benchmarksAndOptions = mx.extract_VM_args(args, useDoubleDash=availableBenchmarks is None)
 
     if availableBenchmarks is None:
         harnessArgs = benchmarksAndOptions
@@ -1123,268 +1123,42 @@
     matches = lambda line: len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0
     return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses)
 
-def _extract_VM_args(args, allowClasspath=False, useDoubleDash=False, defaultAllVMArgs=True):
-    """
-    Partitions a command line into a leading sequence of HotSpot VM options and the rest.
-    """
-    for i in range(0, len(args)):
-        if useDoubleDash:
-            if args[i] == '--':
-                vmArgs = args[:i]
-                remainder = args[i + 1:]
-                return vmArgs, remainder
-        else:
-            if not args[i].startswith('-'):
-                if i != 0 and (args[i - 1] == '-cp' or args[i - 1] == '-classpath'):
-                    if not allowClasspath:
-                        mx.abort('Cannot supply explicit class path option')
-                    else:
-                        continue
-                vmArgs = args[:i]
-                remainder = args[i:]
-                return vmArgs, remainder
-
-    if defaultAllVMArgs:
-        return args, []
-    else:
-        return [], args
-
-def _run_tests(args, harness, annotations, testfile, blacklist, whitelist, regex):
-
-
-    vmArgs, tests = _extract_VM_args(args)
-    for t in tests:
-        if t.startswith('-'):
-            mx.abort('VM option ' + t + ' must precede ' + tests[0])
-
-    candidates = {}
-    for p in mx.projects_opt_limit_to_suites():
-        if mx.java().javaCompliance < p.javaCompliance:
-            continue
-        for c in _find_classes_with_annotations(p, None, annotations).keys():
-            candidates[c] = p
-
-    classes = []
-    if len(tests) == 0:
-        classes = candidates.keys()
-        projectsCp = mx.classpath([pcp.name for pcp in mx.projects_opt_limit_to_suites() if pcp.javaCompliance <= mx.java().javaCompliance])
-    else:
-        projs = set()
-        found = False
-        if len(tests) == 1 and '#' in tests[0]:
-            words = tests[0].split('#')
-            if len(words) != 2:
-                mx.abort("Method specification is class#method: " + tests[0])
-            t, method = words
-
-            for c, p in candidates.iteritems():
-                # prefer exact matches first
-                if t == c:
-                    found = True
-                    classes.append(c)
-                    projs.add(p.name)
-            if not found:
-                for c, p in candidates.iteritems():
-                    if t in c:
-                        found = True
-                        classes.append(c)
-                        projs.add(p.name)
-            if not found:
-                mx.log('warning: no tests matched by substring "' + t)
-            elif len(classes) != 1:
-                mx.abort('More than one test matches substring {0} {1}'.format(t, classes))
+def _find_classpath_arg(vmArgs):
+    for index in range(len(vmArgs)):
+        if vmArgs[index] in ['-cp', '-classpath']:
+            return index + 1, vmArgs[index + 1]
 
-            classes = [c + "#" + method for c in classes]
-        else:
-            for t in tests:
-                if '#' in t:
-                    mx.abort('Method specifications can only be used in a single test: ' + t)
-                for c, p in candidates.iteritems():
-                    if t in c:
-                        found = True
-                        classes.append(c)
-                        projs.add(p.name)
-                if not found:
-                    mx.log('warning: no tests matched by substring "' + t)
-        projectsCp = mx.classpath(projs)
-
-    if blacklist:
-        classes = [c for c in classes if not any((glob.match(c) for glob in blacklist))]
-
-    if whitelist:
-        classes = [c for c in classes if any((glob.match(c) for glob in whitelist))]
-
-    if regex:
-        classes = [c for c in classes if re.search(regex, c)]
-
-    if len(classes) != 0:
-        f_testfile = open(testfile, 'w')
-        for c in classes:
-            f_testfile.write(c + '\n')
-        f_testfile.close()
-        harness(projectsCp, vmArgs)
-
-def _unittest(args, annotations, prefixCp="", blacklist=None, whitelist=None, verbose=False, fail_fast=False, enable_timing=False, regex=None, color=False, eager_stacktrace=False, gc_after_test=False):
-    testfile = os.environ.get('MX_TESTFILE', None)
-    if testfile is None:
-        (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
-        os.close(_)
+def unittest(args):
+    def vmLauncher(vmArgs, mainClass, mainClassArgs):
+        if isJVMCIEnabled(_get_vm()):
+            # Remove entries from class path that are in JVMCI loaded jars
+            cpIndex, cp = _find_classpath_arg(vmArgs)
+            if cp:
+                excluded = set()
+                for jdkDist in _jdkDeployedDists:
+                    dist = mx.distribution(jdkDist.name)
+                    excluded.update([d.output_dir() for d in dist.sorted_deps()])
+                print 'before:', len(cp)
+                cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded])
+                print 'after:', len(cp)
+                vmArgs[cpIndex] = cp
 
-    coreCp = mx.classpath(['com.oracle.graal.test', 'HCFDIS'])
-
-    coreArgs = []
-    if verbose:
-        coreArgs.append('-JUnitVerbose')
-    if fail_fast:
-        coreArgs.append('-JUnitFailFast')
-    if enable_timing:
-        coreArgs.append('-JUnitEnableTiming')
-    if color:
-        coreArgs.append('-JUnitColor')
-    if eager_stacktrace:
-        coreArgs.append('-JUnitEagerStackTrace')
-    if gc_after_test:
-        coreArgs.append('-JUnitGCAfterTest')
-
-
-    def harness(projectsCp, vmArgs):
-        if _get_vm() != 'jvmci':
-            prefixArgs = ['-esa', '-ea']
-        else:
-            prefixArgs = ['-XX:-BootstrapJVMCI', '-esa', '-ea']
-        if gc_after_test:
-            prefixArgs.append('-XX:-DisableExplicitGC')
-        with open(testfile) as fp:
-            testclasses = [l.rstrip() for l in fp.readlines()]
-
-        # Remove entries from class path that are in graal.jar and
-        # run the VM in a mode where application/test classes can
-        # access core Graal classes.
-        cp = prefixCp + coreCp + os.pathsep + projectsCp
-        if isJVMCIEnabled(_get_vm()):
-            excluded = set()
-            for jdkDist in _jdkDeployedDists:
-                dist = mx.distribution(jdkDist.name)
-                excluded.update([d.output_dir() for d in dist.sorted_deps()])
-            cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded])
+            # Run the VM in a mode where application/test classes can
+            # access JVMCI loaded classes.
             vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs
 
-        # suppress menubar and dock when running on Mac
-        vmArgs = ['-Djava.awt.headless=true'] + vmArgs
-
-        if len(testclasses) == 1:
-            # Execute Junit directly when one test is being run. This simplifies
-            # replaying the VM execution in a native debugger (e.g., gdb).
-            vm(prefixArgs + vmArgs + ['-cp', mx._separatedCygpathU2W(cp), 'com.oracle.graal.test.GraalJUnitCore'] + coreArgs + testclasses)
-        else:
-            vm(prefixArgs + vmArgs + ['-cp', mx._separatedCygpathU2W(cp), 'com.oracle.graal.test.GraalJUnitCore'] + coreArgs + ['@' + mx._cygpathU2W(testfile)])
-
-    try:
-        _run_tests(args, harness, annotations, testfile, blacklist, whitelist, regex)
-    finally:
-        if os.environ.get('MX_TESTFILE') is None:
-            os.remove(testfile)
-
-_unittestHelpSuffix = """
-    Unittest options:
-
-      --blacklist <file>     run all testcases not specified in the blacklist
-      --whitelist <file>     run only testcases which are included
-                             in the given whitelist
-      --verbose              enable verbose JUnit output
-      --fail-fast            stop after first JUnit test class that has a failure
-      --enable-timing        enable JUnit test timing
-      --regex <regex>        run only testcases matching a regular expression
-      --color                enable colors output
-      --eager-stacktrace     print stacktrace eagerly
-      --gc-after-test        force a GC after each test
-
-    To avoid conflicts with VM options '--' can be used as delimiter.
-
-    If filters are supplied, only tests whose fully qualified name
-    includes a filter as a substring are run.
-
-    For example, this command line:
-
-       mx unittest -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG BC_aload
-
-    will run all JUnit test classes that contain 'BC_aload' in their
-    fully qualified name and will pass these options to the VM:
-
-        -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG
-
-    To get around command line length limitations on some OSes, the
-    JUnit class names to be executed are written to a file that a
-    custom JUnit wrapper reads and passes onto JUnit proper. The
-    MX_TESTFILE environment variable can be set to specify a
-    file which will not be deleted once the unittests are done
-    (unlike the temporary file otherwise used).
-
-    As with all other commands, using the global '-v' before 'unittest'
-    command will cause mx to show the complete command line
-    it uses to run the VM.
-"""
-
-def unittest(args):
-    """run the JUnit tests (all testcases){0}"""
-
-    parser = ArgumentParser(prog='mx unittest',
-          description='run the JUnit tests',
-          add_help=False,
-          formatter_class=RawDescriptionHelpFormatter,
-          epilog=_unittestHelpSuffix,
-        )
-    parser.add_argument('--blacklist', help='run all testcases not specified in the blacklist', metavar='<path>')
-    parser.add_argument('--whitelist', help='run testcases specified in whitelist only', metavar='<path>')
-    parser.add_argument('--verbose', help='enable verbose JUnit output', action='store_true')
-    parser.add_argument('--fail-fast', help='stop after first JUnit test class that has a failure', action='store_true')
-    parser.add_argument('--enable-timing', help='enable JUnit test timing', action='store_true')
-    parser.add_argument('--regex', help='run only testcases matching a regular expression', metavar='<regex>')
-    parser.add_argument('--color', help='enable color output', action='store_true')
-    parser.add_argument('--eager-stacktrace', help='print stacktrace eagerly', action='store_true')
-    parser.add_argument('--gc-after-test', help='force a GC after each test', action='store_true')
-
-    ut_args = []
-    delimiter = False
-    # check for delimiter
-    while len(args) > 0:
-        arg = args.pop(0)
-        if arg == '--':
-            delimiter = True
-            break
-        ut_args.append(arg)
-
-    if delimiter:
-        # all arguments before '--' must be recognized
-        parsed_args = parser.parse_args(ut_args)
-    else:
-        # parse all know arguments
-        parsed_args, args = parser.parse_known_args(ut_args)
-
-    if parsed_args.whitelist:
-        try:
-            with open(join(_graal_home, parsed_args.whitelist)) as fp:
-                parsed_args.whitelist = [re.compile(fnmatch.translate(l.rstrip())) for l in fp.readlines() if not l.startswith('#')]
-        except IOError:
-            mx.log('warning: could not read whitelist: ' + parsed_args.whitelist)
-    if parsed_args.blacklist:
-        try:
-            with open(join(_graal_home, parsed_args.blacklist)) as fp:
-                parsed_args.blacklist = [re.compile(fnmatch.translate(l.rstrip())) for l in fp.readlines() if not l.startswith('#')]
-        except IOError:
-            mx.log('warning: could not read blacklist: ' + parsed_args.blacklist)
-
-    _unittest(args, ['@Test', '@Parameters'], **parsed_args.__dict__)
+        vm(vmArgs + [mainClass] + mainClassArgs)
+    mx_unittest.unittest(args, vmLauncher=vmLauncher)
 
 def shortunittest(args):
-    """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'{0}"""
+    """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'"""
 
     args = ['--whitelist', 'test/whitelist_shortunittest.txt'] + args
     unittest(args)
 
 def microbench(args):
     """run JMH microbenchmark projects"""
-    vmArgs, jmhArgs = _extract_VM_args(args, useDoubleDash=True)
+    vmArgs, jmhArgs = mx.extract_VM_args(args, useDoubleDash=True)
 
     # look for -f in JMH arguments
     containsF = False
@@ -2107,7 +1881,7 @@
         mx.help_(['jmh'])
         mx.abort(1)
 
-    vmArgs, benchmarksAndJsons = _extract_VM_args(args)
+    vmArgs, benchmarksAndJsons = mx.extract_VM_args(args)
     if isJVMCIEnabled(_get_vm()) and  '-XX:-UseJVMCIClassLoader' not in vmArgs:
         vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs
 
@@ -2337,12 +2111,12 @@
 
 def sl(args):
     """run an SL program"""
-    vmArgs, slArgs = _extract_VM_args(args)
+    vmArgs, slArgs = mx.extract_VM_args(args)
     vm(vmArgs + ['-cp', mx.classpath(["TRUFFLE", "com.oracle.truffle.sl"]), "com.oracle.truffle.sl.SLLanguage"] + slArgs)
 
 def sldebug(args):
     """run a simple command line debugger for the Simple Language"""
-    vmArgs, slArgs = _extract_VM_args(args, useDoubleDash=True)
+    vmArgs, slArgs = mx.extract_VM_args(args, useDoubleDash=True)
     vm(vmArgs + ['-cp', mx.classpath("com.oracle.truffle.sl.tools"), "com.oracle.truffle.sl.tools.debug.SLREPLServer"] + slArgs)
 
 def isJVMCIEnabled(vm):
@@ -2534,6 +2308,9 @@
             continue
 
         csConfig = join(mx.project(p.checkstyleProj).dir, '.checkstyle_checks.xml')
+        if not exists(csConfig):
+            mx.log('Cannot check headers for ' + p.name + ' - ' + csConfig + ' does not exist')
+            continue
         dom = xml.dom.minidom.parse(csConfig)
         for module in dom.getElementsByTagName('module'):
             if module.getAttribute('name') == 'RegexpHeader':
@@ -2581,9 +2358,9 @@
         'gate' : [gate, '[-options]'],
         'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
         'microbench' : [microbench, '[VM options] [-- [JMH options]]'],
-        'unittest' : [unittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix],
         'makejmhdeps' : [makejmhdeps, ''],
-        'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix],
+        'unittest' : [unittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix],
+        'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix],
         'jacocoreport' : [jacocoreport, '[output directory]'],
         'site' : [site, '[-options]'],
         'vm': [vm, '[-options] class [args...]'],