Esempio n. 1
0
def _find_classes_by_annotated_methods(annotations, suite):
    """
    Scan distributions from binary suite dependencies for classes contain at least one method
    with an annotation from 'annotations' and return a dictionary from fully qualified class
    names to the distribution containing the class.
    """
    binarySuiteDists = [d for d in mx.dependencies(opt_limit_to_suite=True) if d.isJARDistribution() and
                        isinstance(d.suite, mx.BinarySuite) and (not suite or suite == d.suite)]
    if len(binarySuiteDists) != 0:
        # Ensure Java support class is built
        mx.build(['--dependencies', 'com.oracle.mxtool.junit'])

        # Create map from jar file to the binary suite distribution defining it
        jars = {d.classpath_repr() : d for d in binarySuiteDists}

        cp = mx.classpath(['com.oracle.mxtool.junit'] + [d.name for d in binarySuiteDists])
        out = mx.OutputCapture()
        mx.run_java(['-cp', cp] + ['com.oracle.mxtool.junit.FindClassesByAnnotatedMethods'] + annotations + jars.keys(), out=out)
        candidates = {}
        for line in out.data.strip().split('\n'):
            name, jar = line.split(' ')
            # Record class name to the binary suite distribution containing it
            candidates[name] = jars[jar]
        return candidates
    return {}
Esempio n. 2
0
def _find_classes_by_annotated_methods(annotations, suite):
    """
    Scan distributions from binary suite dependencies for classes contain at least one method
    with an annotation from 'annotations' and return a dictionary from fully qualified class
    names to the distribution containing the class.
    """
    binarySuiteDists = [
        d for d in mx.dependencies(opt_limit_to_suite=True)
        if d.isJARDistribution() and isinstance(d.suite, mx.BinarySuite) and (
            not suite or suite == d.suite)
    ]
    if len(binarySuiteDists) != 0:
        # Ensure Java support class is built
        mx.build(['--dependencies', 'com.oracle.mxtool.junit'])

        # Create map from jar file to the binary suite distribution defining it
        jars = {d.classpath_repr(): d for d in binarySuiteDists}

        cp = mx.classpath(['com.oracle.mxtool.junit'] +
                          [d.name for d in binarySuiteDists])
        out = mx.OutputCapture()
        mx.run_java(['-cp', cp] +
                    ['com.oracle.mxtool.junit.FindClassesByAnnotatedMethods'] +
                    annotations + jars.keys(),
                    out=out)
        candidates = {}
        for line in out.data.strip().split('\n'):
            name, jar = line.split(' ')
            # Record class name to the binary suite distribution containing it
            candidates[name] = jars[jar]
        return candidates
    return {}
Esempio n. 3
0
def mx_post_parse_cmd_line(opts):

    def _uses_truffle_dsl_processor(dist):
        for dep in dist.deps:
            if dep.name.startswith('TRUFFLE_DSL_PROCESSOR'):
                return True
        truffle_dsl_processors = set()
        def visit(dep, edge):
            if dep is not dist and dep.isJavaProject():
                for ap in dep.annotation_processors():
                    if ap.name.startswith('TRUFFLE_DSL_PROCESSOR'):
                        truffle_dsl_processors.add(ap)
        dist.walk_deps(visit=visit)
        return len(truffle_dsl_processors) != 0

    for d in mx.dependencies():
        if d.isJARDistribution():
            if _uses_truffle_dsl_processor(d):
                d.set_archiveparticipant(TruffleArchiveParticipant())
Esempio n. 4
0
def mx_post_parse_cmd_line(opts):

    def _uses_truffle_dsl_processor(dist):
        for dep in dist.deps:
            if dep.name.startswith('TRUFFLE_DSL_PROCESSOR'):
                return True
        truffle_dsl_processors = set()
        def visit(dep, edge):
            if dep is not dist and dep.isJavaProject():
                for ap in dep.annotation_processors():
                    if ap.name.startswith('TRUFFLE_DSL_PROCESSOR'):
                        truffle_dsl_processors.add(ap)
        dist.walk_deps(visit=visit)
        return len(truffle_dsl_processors) != 0

    for d in mx.dependencies():
        if d.isJARDistribution():
            if _uses_truffle_dsl_processor(d):
                d.set_archiveparticipant(TruffleArchiveParticipant())
Esempio n. 5
0
def find_test_candidates(annotations, suite, jdk, buildCacheDir='unittest'):
    """
    Finds all classes containing methods annotated with one of the supplied annotations.
    To speed up subsequent invocations, the results are cached in the `buildCacheDir`.

    :param list annotations: a list of annotations to recognize test methods, e.g. ['@Test', '@Parameters']
    :param suite: the mx suite in which to look for test classes. If no suite is given, the primary suite is used.
    :param JDKConfig jdk: the JDK for which the list of classes must be found
    :param str buildCacheDir: a path relative to the mx suite output root that is used to store the cache files.
    :return: a dictionary associating each found test class with the distribution it occurs in.
    """

    assert not isabs(buildCacheDir), "buildCacheDir must be a relative path"
    compat_suite = suite if suite else mx.primary_suite()
    if suite != mx._mx_suite and compat_suite.getMxCompatibility(
    ).useDistsForUnittest():
        jar_distributions = [
            d for d in mx.sorted_dists()
            if d.isJARDistribution() and exists(d.classpath_repr(
                resolve=False)) and (not suite or d.suite == suite)
        ]
        # find a corresponding distribution for each test
        candidates = _find_classes_by_annotated_methods(
            annotations, jar_distributions, buildCacheDir, jdk)
    else:
        binary_deps = [
            d for d in mx.dependencies(opt_limit_to_suite=True)
            if d.isJARDistribution() and isinstance(d.suite, mx.BinarySuite)
            and (not suite or suite == d.suite)
        ]
        candidates = _find_classes_by_annotated_methods(
            annotations, binary_deps, buildCacheDir, jdk)
        for p in mx.projects(opt_limit_to_suite=True):
            if not p.isJavaProject():
                continue
            if suite and not p.suite == suite:
                continue
            if jdk.javaCompliance < p.javaCompliance:
                continue
            for c in _find_classes_with_annotations(p, None, annotations):
                candidates[c] = p
    return candidates
Esempio n. 6
0
def suite_classpath():
    """Get the classpath containing only the current suite's dependencies, removing Graal projects (if any) from it"""
    dependencies = mx.dependencies(True)
    dependencies = itertools.ifilter(lambda d: not d.isNativeProject(),
                                     dependencies)
    dependencies = itertools.ifilter(lambda d: not d.isPackedResourceLibrary(),
                                     dependencies)
    dependencies = [d.name for d in dependencies]
    cp = mx.classpath(dependencies)
    cp_list = cp.split(os.pathsep)
    sanitized_list = []
    for entry in cp_list:
        include = True
        if entry.find("com.oracle.graal") >= 0 or entry.find(
                "com.oracle.truffle") >= 0 or entry.find("graal/dists") >= 0:
            include = False
        if include:
            sanitized_list.append(entry)
    result = os.pathsep.join(sanitized_list)
    return result
Esempio n. 7
0
def _run_tests(args, harness, vmLauncher, annotations, testfile, blacklist,
               whitelist, regex, suite):
    vmArgs, tests = mx.extract_VM_args(args)
    for t in tests:
        if t.startswith('-'):
            mx.abort('VM option ' + t + ' must precede ' + tests[0])

    # this is what should be used
    compat_suite = suite if suite else mx.primary_suite()
    if suite != mx._mx_suite and compat_suite.getMxCompatibility(
    ).useDistsForUnittest():
        jar_distributions = [
            d for d in mx.sorted_dists()
            if d.isJARDistribution() and exists(d.classpath_repr(
                resolve=False)) and (not suite or d.suite == suite)
        ]
        # find a corresponding distribution for each test
        candidates = _find_classes_by_annotated_methods(
            annotations, jar_distributions, vmLauncher.jdk())
    else:
        binary_deps = [
            d for d in mx.dependencies(opt_limit_to_suite=True)
            if d.isJARDistribution() and isinstance(d.suite, mx.BinarySuite)
            and (not suite or suite == d.suite)
        ]
        candidates = _find_classes_by_annotated_methods(
            annotations, binary_deps, vmLauncher.jdk())
        for p in mx.projects(opt_limit_to_suite=True):
            if not p.isJavaProject():
                continue
            if suite and not p.suite == suite:
                continue
            if vmLauncher.jdk().javaCompliance < p.javaCompliance:
                continue
            for c in _find_classes_with_annotations(p, None, annotations):
                candidates[c] = p

    classes = []
    if len(tests) == 0:
        classes = candidates.keys()
        depsContainingTests = set(candidates.values())
    else:
        depsContainingTests = 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)
                    depsContainingTests.add(p)
            if not found:
                for c, p in candidates.iteritems():
                    if t in c:
                        found = True
                        classes.append(c)
                        depsContainingTests.add(p)
            if not found:
                mx.warn('no tests matched by substring: ' + t +
                        ' (did you forget to run "mx build"?)')
            elif len(classes) != 1:
                mx.abort('More than one test matches substring {0} {1}'.format(
                    t, classes))

            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)
                        depsContainingTests.add(p)
                if not found:
                    mx.warn('no tests matched by substring: ' + t +
                            ' (did you forget to run "mx build"?)')

    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(depsContainingTests, vmLauncher, vmArgs)
Esempio n. 8
0
def _unittest_config_participant(config):
    vmArgs, mainClass, mainClassArgs = config
    cpIndex, cp = mx.find_classpath_arg(vmArgs)
    if cp:
        cp = _uniqify(cp.split(os.pathsep))
        if isJDK8:
            # Remove entries from class path that are in Graal or on the boot class path
            redundantClasspathEntries = set()
            for dist in [entry.dist() for entry in _jvmci_classpath]:
                redundantClasspathEntries.update((d.output_dir() for d in dist.archived_deps() if d.isJavaProject()))
                redundantClasspathEntries.add(dist.path)
            cp = os.pathsep.join([e for e in cp if e not in redundantClasspathEntries])
            vmArgs[cpIndex] = cp
        else:
            deployedModules = []
            redundantClasspathEntries = set()
            for dist in [entry.dist() for entry in _jvmci_classpath] + _bootclasspath_appends:
                deployedModule = as_java_module(dist, jdk)
                deployedModules.append(deployedModule)
                redundantClasspathEntries.update(mx.classpath(dist, preferProjects=False, jdk=jdk).split(os.pathsep))
                redundantClasspathEntries.update(mx.classpath(dist, preferProjects=True, jdk=jdk).split(os.pathsep))
                if hasattr(dist, 'overlaps'):
                    for o in dist.overlaps:
                        path = mx.distribution(o).classpath_repr()
                        if path:
                            redundantClasspathEntries.add(path)

            # Remove entries from the class path that are in the deployed modules
            cp = [classpathEntry for classpathEntry in cp if classpathEntry not in redundantClasspathEntries]
            vmArgs[cpIndex] = os.pathsep.join(cp)

            # Junit libraries are made into automatic modules so that they are visible to tests
            # patched into modules. These automatic modules must be declared to be read by
            # Graal which means they must also be made root modules (i.e., ``--add-modules``)
            # since ``--add-reads`` can only be applied to root modules.
            junitCp = [e.classpath_repr() for e in mx.classpath_entries(['JUNIT'])]
            junitModules = [_automatic_module_name(e) for e in junitCp]
            vmArgs.append('--module-path=' + os.pathsep.join(junitCp))
            vmArgs.append('--add-modules=' + ','.join(junitModules + [m.name for m in deployedModules]))
            for deployedModule in deployedModules:
                vmArgs.append('--add-reads=' + deployedModule.name + '=' + ','.join(junitModules))

            # Explicitly export concealed JVMCI packages required by Graal. Even though
            # normally exported via jdk.vm.ci.services.Services.exportJVMCITo(), the
            # Junit harness wants to access JVMCI classes (e.g., when loading classes
            # to find test methods) without going through that entry point.
            addedExports = {}
            for deployedModule in deployedModules:
                for concealingModule, packages in deployedModule.concealedRequires.iteritems():
                    if concealingModule == 'jdk.vm.ci':
                        for package in packages:
                            addedExports.setdefault(concealingModule + '/' + package, set()).add(deployedModule.name)

            pathToDep = {p.output_dir() if p.isJavaProject() else p.path: p for p in mx.dependencies() if p.isJavaProject() or p.isJARDistribution()}
            for classpathEntry in cp:
                # Export concealed packages used by the class path entry
                _add_exports_for_concealed_packages(classpathEntry, pathToDep, addedExports, 'ALL-UNNAMED', deployedModules)

                for deployedModule in deployedModules:
                    assert deployedModule.dist.path != classpathEntry, deployedModule.dist.path + ' should no longer be on the class path'
                    # Ensure the class path entry does not define packages already defined by the module.
                    # Packages definitions cannot be split between modules.
                    classpathEntryPackages = frozenset(_defined_packages(classpathEntry))
                    intersection = classpathEntryPackages.intersection(deployedModule.packages)
                    if intersection:
                        mx.abort(classpathEntry + ' cannot extend package(s) defined in the module ' + deployedModule.name + ': ' + ', '.join(intersection))

            vmArgs.extend(['--add-exports=' + export + '=' + ','.join(sorted(targets)) for export, targets in addedExports.iteritems()])

    if isJDK8:
        # Run the VM in a mode where application/test classes can
        # access JVMCI loaded classes.
        vmArgs.append('-XX:-UseJVMCIClassLoader')

    return (vmArgs, mainClass, mainClassArgs)
Esempio n. 9
0
def _run_tests(args, harness, vmLauncher, annotations, testfile, blacklist, whitelist, regex, suite):
    vmArgs, tests = mx.extract_VM_args(args)
    for t in tests:
        if t.startswith('-'):
            mx.abort('VM option ' + t + ' must precede ' + tests[0])

    # this is what should be used
    compat_suite = suite if suite else mx.primary_suite()
    if suite != mx._mx_suite and compat_suite.getMxCompatibility().useDistsForUnittest():
        jar_distributions = [d for d in mx.sorted_dists() if d.isJARDistribution() and (not suite or d.suite == suite)]
        # find a corresponding distribution for each test
        candidates = _find_classes_by_annotated_methods(annotations, jar_distributions, vmLauncher.jdk())
    else:
        binary_deps = [d for d in mx.dependencies(opt_limit_to_suite=True) if d.isJARDistribution() and
                       isinstance(d.suite, mx.BinarySuite) and (not suite or suite == d.suite)]
        candidates = _find_classes_by_annotated_methods(annotations, binary_deps, vmLauncher.jdk())
        for p in mx.projects(opt_limit_to_suite=True):
            if not p.isJavaProject():
                continue
            if suite and not p.suite == suite:
                continue
            if vmLauncher.jdk().javaCompliance < p.javaCompliance:
                continue
            for c in _find_classes_with_annotations(p, None, annotations):
                candidates[c] = p

    classes = []
    if len(tests) == 0:
        classes = candidates.keys()
        depsContainingTests = set(candidates.values())
    else:
        depsContainingTests = 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)
                    depsContainingTests.add(p)
            if not found:
                for c, p in candidates.iteritems():
                    if t in c:
                        found = True
                        classes.append(c)
                        depsContainingTests.add(p)
            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))

            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)
                        depsContainingTests.add(p)
                if not found:
                    mx.log('warning: no tests matched by substring: ' + t)

    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(depsContainingTests, vmLauncher, vmArgs)
Esempio n. 10
0
def _unittest_config_participant(config):
    vmArgs, mainClass, mainClassArgs = config
    cpIndex, cp = mx.find_classpath_arg(vmArgs)
    if cp:
        cp = _uniqify(cp.split(os.pathsep))
        if isJDK8:
            # Remove entries from class path that are in Graal or on the boot class path
            redundantClasspathEntries = set()
            for dist in [entry.dist() for entry in _jvmci_classpath]:
                redundantClasspathEntries.update(
                    (d.output_dir() for d in dist.archived_deps()
                     if d.isJavaProject()))
                redundantClasspathEntries.add(dist.path)
            cp = os.pathsep.join(
                [e for e in cp if e not in redundantClasspathEntries])
            vmArgs[cpIndex] = cp
        else:
            deployedModules = []
            redundantClasspathEntries = set()
            for dist in [entry.dist() for entry in _jvmci_classpath
                         ] + _bootclasspath_appends:
                deployedModule = as_java_module(dist, jdk)
                deployedModules.append(deployedModule)
                redundantClasspathEntries.update(
                    mx.classpath(dist, preferProjects=False,
                                 jdk=jdk).split(os.pathsep))
                redundantClasspathEntries.update(
                    mx.classpath(dist, preferProjects=True,
                                 jdk=jdk).split(os.pathsep))
                if hasattr(dist, 'overlaps'):
                    for o in dist.overlaps:
                        path = mx.distribution(o).classpath_repr()
                        if path:
                            redundantClasspathEntries.add(path)

            # Remove entries from the class path that are in the deployed modules
            cp = [
                classpathEntry for classpathEntry in cp
                if classpathEntry not in redundantClasspathEntries
            ]
            vmArgs[cpIndex] = os.pathsep.join(cp)

            # Junit libraries are made into automatic modules so that they are visible to tests
            # patched into modules. These automatic modules must be declared to be read by
            # Graal which means they must also be made root modules (i.e., ``--add-modules``)
            # since ``--add-reads`` can only be applied to root modules.
            junitCp = [
                e.classpath_repr() for e in mx.classpath_entries(['JUNIT'])
            ]
            junitModules = [_automatic_module_name(e) for e in junitCp]
            vmArgs.append('--module-path=' + os.pathsep.join(junitCp))
            vmArgs.append('--add-modules=' +
                          ','.join(junitModules +
                                   [m.name for m in deployedModules]))
            for deployedModule in deployedModules:
                vmArgs.append('--add-reads=' + deployedModule.name + '=' +
                              ','.join(junitModules))

            # Explicitly export concealed JVMCI packages required by Graal. Even though
            # normally exported via jdk.vm.ci.services.Services.exportJVMCITo(), the
            # Junit harness wants to access JVMCI classes (e.g., when loading classes
            # to find test methods) without going through that entry point.
            addedExports = {}
            for deployedModule in deployedModules:
                for concealingModule, packages in deployedModule.concealedRequires.iteritems(
                ):
                    if concealingModule == 'jdk.vm.ci':
                        for package in packages:
                            addedExports.setdefault(
                                concealingModule + '/' + package,
                                set()).add(deployedModule.name)

            pathToDep = {
                p.output_dir() if p.isJavaProject() else p.path: p
                for p in mx.dependencies()
                if p.isJavaProject() or p.isJARDistribution()
            }
            for classpathEntry in cp:
                # Export concealed packages used by the class path entry
                _add_exports_for_concealed_packages(classpathEntry, pathToDep,
                                                    addedExports,
                                                    'ALL-UNNAMED',
                                                    deployedModules)

                for deployedModule in deployedModules:
                    assert deployedModule.dist.path != classpathEntry, deployedModule.dist.path + ' should no longer be on the class path'
                    # Ensure the class path entry does not define packages already defined by the module.
                    # Packages definitions cannot be split between modules.
                    classpathEntryPackages = frozenset(
                        _defined_packages(classpathEntry))
                    intersection = classpathEntryPackages.intersection(
                        deployedModule.packages)
                    if intersection:
                        mx.abort(
                            classpathEntry +
                            ' cannot extend package(s) defined in the module '
                            + deployedModule.name + ': ' +
                            ', '.join(intersection))

            vmArgs.extend([
                '--add-exports=' + export + '=' + ','.join(sorted(targets))
                for export, targets in addedExports.iteritems()
            ])

    if isJDK8:
        # Run the VM in a mode where application/test classes can
        # access JVMCI loaded classes.
        vmArgs.append('-XX:-UseJVMCIClassLoader')

    return (vmArgs, mainClass, mainClassArgs)