def test_resolve_with_inexact_coord(rule_runner: RuleRunner) -> None:
    resolved_lockfile = rule_runner.request(
        CoursierResolvedLockfile,
        [
            # Note the open-ended coordinate here.  We will still resolve this for the user, but the result
            # will be exact and pinned.  As noted above, this is an especially brittle unit test, but version
            # 4.8 was chosen because it has multiple patch versions and no new versions have been uploaded
            # to 4.8.x in over a decade.
            ArtifactRequirements(
                [Coordinate(group="junit", artifact="junit", version="4.8+")]),
        ],
    )

    assert resolved_lockfile == CoursierResolvedLockfile(
        entries=(CoursierLockfileEntry(
            coord=Coordinate(group="junit", artifact="junit", version="4.8.2"),
            file_name="junit-4.8.2.jar",
            direct_dependencies=Coordinates([]),
            dependencies=Coordinates([]),
            file_digest=FileDigest(
                fingerprint=
                "a2aa2c3bb2b72da76c3e6a71531f1eefdc350494819baf2b1d80d7146e020f9e",
                serialized_bytes_length=237344,
            ),
        ), ))
Esempio n. 2
0
def java_parser_artifact_requirements() -> ArtifactRequirements:
    return ArtifactRequirements([
        Coordinate(group="com.fasterxml.jackson.core",
                   artifact="jackson-databind",
                   version="2.12.4"),
        Coordinate(
            group="com.github.javaparser",
            artifact="javaparser-symbol-solver-core",
            version="3.23.0",
        ),
    ], )
def test_resolve_conflicting(rule_runner: RuleRunner) -> None:
    with engine_error(
            ProcessExecutionFailure,
            contains="Resolution error: Unsatisfied rule Strict(junit:junit)"):
        rule_runner.request(
            CoursierResolvedLockfile,
            [
                ArtifactRequirements([
                    Coordinate(
                        group="junit", artifact="junit", version="4.8.1"),
                    Coordinate(
                        group="junit", artifact="junit", version="4.8.2"),
                ]),
            ],
        )
def test_fetch_one_coord_with_transitive_deps(rule_runner: RuleRunner) -> None:
    junit_coord = Coordinate(group="junit", artifact="junit", version="4.13.2")
    classpath_entry = rule_runner.request(
        ClasspathEntry,
        [
            CoursierLockfileEntry(
                coord=junit_coord,
                file_name="junit-4.13.2.jar",
                direct_dependencies=Coordinates([HAMCREST_COORD]),
                dependencies=Coordinates([HAMCREST_COORD]),
                file_digest=FileDigest(
                    fingerprint=
                    "8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3",
                    serialized_bytes_length=384581,
                ),
            )
        ],
    )
    assert classpath_entry.filenames == ("junit-4.13.2.jar", )
    file_digest = rule_runner.request(
        FileDigest,
        [ExtractFileDigest(classpath_entry.digest, "junit-4.13.2.jar")])
    assert file_digest == FileDigest(
        fingerprint=
        "8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3",
        serialized_bytes_length=384581,
    )
def test_resolve_with_transitive_deps(rule_runner: RuleRunner) -> None:
    junit_coord = Coordinate(group="junit", artifact="junit", version="4.13.2")
    resolved_lockfile = rule_runner.request(
        CoursierResolvedLockfile,
        [
            ArtifactRequirements([junit_coord]),
        ],
    )

    assert resolved_lockfile == CoursierResolvedLockfile(entries=(
        CoursierLockfileEntry(
            coord=junit_coord,
            file_name="junit-4.13.2.jar",
            direct_dependencies=Coordinates([HAMCREST_COORD]),
            dependencies=Coordinates([HAMCREST_COORD]),
            file_digest=FileDigest(
                fingerprint=
                "8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3",
                serialized_bytes_length=384581,
            ),
        ),
        CoursierLockfileEntry(
            coord=HAMCREST_COORD,
            file_name="hamcrest-core-1.3.jar",
            direct_dependencies=Coordinates([]),
            dependencies=Coordinates([]),
            file_digest=FileDigest(
                fingerprint=
                "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9",
                serialized_bytes_length=45024,
            ),
        ),
    ))
def test_fetch_one_coord_with_mismatched_coord(
        rule_runner: RuleRunner) -> None:
    """This test demonstrates that fetch_one_coord is picky about inexact coordinates.

    Even though the expected jar was downloaded, the coordinate in the lockfile entry was inexact, meaning
    it wasn't an exact string match for the coordinate fetched and reported by Coursier, which is exact.

    This shouldn't happen in practice, because these lockfile entries are ultimately derived from Coursier
    reports which always give exact coordinate strings.
    """
    expected_exception_msg = (
        r'Coursier resolved coord.*?"org.hamcrest:hamcrest-core:1.3".*?'
        r'does not match requested coord.*?"org.hamcrest:hamcrest-core:1.3\+".*?'
    )
    lockfile_entry = CoursierLockfileEntry(
        coord=Coordinate(group="org.hamcrest",
                         artifact="hamcrest-core",
                         version="1.3+"),
        file_name="hamcrest-core-1.3.jar",
        direct_dependencies=Coordinates([]),
        dependencies=Coordinates([]),
        file_digest=FileDigest(
            fingerprint=
            "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9",
            serialized_bytes_length=45024,
        ),
    )
    with pytest.raises(ExecutionError, match=expected_exception_msg):
        rule_runner.request(ClasspathEntry, [lockfile_entry])
Esempio n. 7
0
def test_compile_with_maven_deps(rule_runner: RuleRunner) -> None:
    resolved_joda_lockfile = CoursierResolvedLockfile(
        entries=(CoursierLockfileEntry(
            coord=Coordinate(
                group="joda-time", artifact="joda-time", version="2.10.10"),
            file_name="joda-time-2.10.10.jar",
            direct_dependencies=Coordinates([]),
            dependencies=Coordinates([]),
            file_digest=FileDigest(
                fingerprint=
                "dd8e7c92185a678d1b7b933f31209b6203c8ffa91e9880475a1be0346b9617e3",
                serialized_bytes_length=644419,
            ),
        ), ))
    rule_runner.write_files({
        "BUILD":
        dedent("""\
                jvm_artifact(
                    name = "joda-time_joda-time",
                    group = "joda-time",
                    artifact = "joda-time",
                    version = "2.10.10",
                )
                scala_sources(
                    name = 'main',
                    dependencies = [":joda-time_joda-time"],
                )
                """),
        "coursier_resolve.lockfile":
        resolved_joda_lockfile.to_json().decode("utf-8"),
        "Example.scala":
        dedent("""
                package org.pantsbuild.example

                import org.joda.time.DateTime

                object Main {
                    def main(args: Array[String]): Unit = {
                        val dt = new DateTime()
                        println(dt.getYear)
                    }
                }
                """),
    })
    request = CompileScalaSourceRequest(
        component=expect_single_expanded_coarsened_target(
            rule_runner, Address(spec_path="", target_name="main")),
        resolve=make_resolve(rule_runner),
    )
    compiled_classfiles = rule_runner.request(ClasspathEntry, [request])
    classpath = rule_runner.request(RenderedClasspath,
                                    [compiled_classfiles.digest])
    assert classpath.content == {
        ".Example.scala.main.jar": {
            "META-INF/MANIFEST.MF",
            "org/pantsbuild/example/Main$.class",
            "org/pantsbuild/example/Main.class",
        }
    }
Esempio n. 8
0
def test_compile_with_maven_deps(rule_runner: RuleRunner) -> None:
    resolved_joda_lockfile = CoursierResolvedLockfile(
        entries=(CoursierLockfileEntry(
            coord=Coordinate(
                group="joda-time", artifact="joda-time", version="2.10.10"),
            file_name="joda-time-2.10.10.jar",
            direct_dependencies=Coordinates([]),
            dependencies=Coordinates([]),
            file_digest=FileDigest(
                fingerprint=
                "dd8e7c92185a678d1b7b933f31209b6203c8ffa91e9880475a1be0346b9617e3",
                serialized_bytes_length=644419,
            ),
        ), ))
    rule_runner.write_files({
        "BUILD":
        dedent("""\
                jvm_artifact(
                    name = "joda-time_joda-time",
                    group = "joda-time",
                    artifact = "joda-time",
                    version = "2.10.10",
                )

                java_sources(
                    name = 'main',

                    dependencies = [
                        ':joda-time_joda-time',
                    ]
                )
                """),
        "coursier_resolve.lockfile":
        resolved_joda_lockfile.to_json().decode("utf-8"),
        "Example.java":
        dedent("""
                package org.pantsbuild.example;

                import org.joda.time.DateTime;

                public class Example {
                    public static void main(String[] args) {
                        DateTime dt = new DateTime();
                        System.out.println(dt.getYear());
                    }
                }
                """),
    })
    request = CompileJavaSourceRequest(
        component=expect_single_expanded_coarsened_target(
            rule_runner, Address(spec_path="", target_name="main")),
        resolve=make_resolve(rule_runner),
    )
    compiled_classfiles = rule_runner.request(ClasspathEntry, [request])
    classpath = rule_runner.request(RenderedClasspath,
                                    [compiled_classfiles.digest])
    assert classpath.content == {
        ".Example.java.main.jar": {"org/pantsbuild/example/Example.class"}
    }
Esempio n. 9
0
def java_parser_artifact_requirements() -> ArtifactRequirements:
    # Update in concert with the target definition for `java_parser`.
    return ArtifactRequirements(
        [
            Coordinate(
                group="com.fasterxml.jackson.core", artifact="jackson-databind", version="2.12.4"
            ),
            Coordinate(
                group="com.fasterxml.jackson.datatype",
                artifact="jackson-datatype-jdk8",
                version="2.12.4",
            ),
            Coordinate(
                group="com.github.javaparser",
                artifact="javaparser-symbol-solver-core",
                version="3.23.0",
            ),
        ],
    )
Esempio n. 10
0
def _coordinate_from_target(tgt: Target) -> Coordinate:
    group = tgt[JvmArtifactGroupField].value
    if not group:
        raise InvalidTargetException(
            f"The `group` field of {tgt.alias} target {tgt.address} must be set."
        )

    artifact = tgt[JvmArtifactArtifactField].value
    if not artifact:
        raise InvalidTargetException(
            f"The `artifact` field of {tgt.alias} target {tgt.address} must be set."
        )

    version = tgt[JvmArtifactVersionField].value
    if not version:
        raise InvalidTargetException(
            f"The `version` field of {tgt.alias} target {tgt.address} must be set."
        )

    return Coordinate(
        group=group,
        artifact=artifact,
        version=version,
    )
Esempio n. 11
0
async def compile_scala_source(
    bash: BashBinary,
    coursier: Coursier,
    jdk_setup: JdkSetup,
    scala: ScalaSubsystem,
    union_membership: UnionMembership,
    request: CompileScalaSourceRequest,
) -> FallibleClasspathEntry:
    # Request classpath entries for our direct dependencies.
    direct_dependency_classpath_entries = FallibleClasspathEntry.if_all_succeeded(
        await MultiGet(
            Get(
                FallibleClasspathEntry,
                ClasspathEntryRequest,
                ClasspathEntryRequest.for_targets(union_membership,
                                                  component=coarsened_dep,
                                                  resolve=request.resolve),
            ) for coarsened_dep in request.component.dependencies))
    if direct_dependency_classpath_entries is None:
        return FallibleClasspathEntry(
            description=str(request.component),
            result=CompileResult.DEPENDENCY_FAILED,
            output=None,
            exit_code=1,
        )

    component_members_with_sources = tuple(t for t in request.component.members
                                           if t.has_field(SourcesField))
    component_members_and_source_files = zip(
        component_members_with_sources,
        await MultiGet(
            Get(
                SourceFiles,
                SourceFilesRequest(
                    (t.get(SourcesField), ),
                    for_sources_types=(ScalaSourceField, ),
                    enable_codegen=True,
                ),
            ) for t in component_members_with_sources),
    )

    component_members_and_scala_source_files = [
        (target, sources)
        for target, sources in component_members_and_source_files
        if sources.snapshot.digest != EMPTY_DIGEST
    ]

    if not component_members_and_scala_source_files:
        # Is a generator, and so exports all of its direct deps.
        exported_digest = await Get(
            Digest,
            MergeDigests(cpe.digest
                         for cpe in direct_dependency_classpath_entries))
        classpath_entry = ClasspathEntry.merge(
            exported_digest, direct_dependency_classpath_entries)
        return FallibleClasspathEntry(
            description=str(request.component),
            result=CompileResult.SUCCEEDED,
            output=classpath_entry,
            exit_code=0,
        )

    (
        tool_classpath,
        merged_transitive_dependency_classpath_entries_digest,
    ) = await MultiGet(
        Get(
            MaterializedClasspath,
            MaterializedClasspathRequest(
                prefix="__toolcp",
                artifact_requirements=(ArtifactRequirements([
                    Coordinate(
                        group="org.scala-lang",
                        artifact="scala-compiler",
                        version=scala.version,
                    ),
                    Coordinate(
                        group="org.scala-lang",
                        artifact="scala-library",
                        version=scala.version,
                    ),
                ]), ),
            ),
        ),
        Get(
            Digest,
            # Flatten the entire transitive classpath.
            MergeDigests(classfiles.digest
                         for classfiles in ClasspathEntry.closure(
                             direct_dependency_classpath_entries)),
        ),
    )

    usercp = "__cp"
    prefixed_transitive_dependency_classpath_digest = await Get(
        Digest,
        AddPrefix(merged_transitive_dependency_classpath_entries_digest,
                  usercp))

    merged_digest = await Get(
        Digest,
        MergeDigests((
            prefixed_transitive_dependency_classpath_digest,
            tool_classpath.digest,
            jdk_setup.digest,
            *(sources.snapshot.digest
              for _, sources in component_members_and_scala_source_files),
        )),
    )

    classpath_arg = ClasspathEntry.arg(
        ClasspathEntry.closure(direct_dependency_classpath_entries),
        prefix=usercp)

    output_file = f"{request.component.representative.address.path_safe_spec}.jar"
    process_result = await Get(
        FallibleProcessResult,
        Process(
            argv=[
                *jdk_setup.args(bash, tool_classpath.classpath_entries()),
                "scala.tools.nsc.Main",
                "-bootclasspath",
                ":".join(tool_classpath.classpath_entries()),
                *(("-classpath", classpath_arg) if classpath_arg else ()),
                "-d",
                output_file,
                *sorted(
                    chain.from_iterable(
                        sources.snapshot.files for _, sources in
                        component_members_and_scala_source_files)),
            ],
            input_digest=merged_digest,
            use_nailgun=jdk_setup.digest,
            output_files=(output_file, ),
            description=f"Compile {request.component} with scalac",
            level=LogLevel.DEBUG,
            append_only_caches=jdk_setup.append_only_caches,
            env=jdk_setup.env,
        ),
    )
    output: ClasspathEntry | None = None
    if process_result.exit_code == 0:
        output = ClasspathEntry(process_result.output_digest, (output_file, ),
                                direct_dependency_classpath_entries)

    return FallibleClasspathEntry.from_fallible_process_result(
        str(request.component),
        process_result,
        output,
    )
Esempio n. 12
0
async def setup_jdk(coursier: Coursier, javac: JavacSubsystem,
                    bash: BashBinary) -> JdkSetup:
    nailgun = await Get(
        ResolvedClasspathEntry,
        CoursierLockfileEntry(
            coord=Coordinate.from_coord_str(
                "com.martiansoftware:nailgun-server:0.9.1"),
            file_name="nailgun-server-0.9.1.jar",
            direct_dependencies=Coordinates(),
            dependencies=Coordinates(),
            file_digest=FileDigest(
                fingerprint=
                "4518faa6bf4bd26fccdc4d85e1625dc679381a08d56872d8ad12151dda9cef25",
                serialized_bytes_length=32927,
            ),
        ),
    )

    if javac.options.jdk == "system":
        coursier_jdk_option = "--system-jvm"
    else:
        coursier_jdk_option = f"--jvm={javac.options.jdk}"
    java_home_command = f"{coursier.coursier.exe} java-home {coursier_jdk_option}"

    java_version_result = await Get(
        FallibleProcessResult,
        Process(
            argv=(
                bash.path,
                "-c",
                f"$({java_home_command})/bin/java -version",
            ),
            input_digest=coursier.digest,
            description=f"Ensure download of JDK {coursier_jdk_option}.",
            cache_scope=ProcessCacheScope.PER_RESTART_SUCCESSFUL,
        ),
    )

    if java_version_result.exit_code != 0:
        raise ValueError(
            f"Failed to locate Java for JDK `{javac.options.jdk}`:\n"
            f"{java_version_result.stderr.decode('utf-8')}")

    java_version = java_version_result.stdout.decode("utf-8").strip()

    # TODO: Locate `ln`.
    jdk_preparation_script = textwrap.dedent(f"""\
        # pants javac script using Coursier {coursier_jdk_option}. `java -version`: {java_version}"
        set -eu

        /bin/ln -s "$({java_home_command})" "{JdkSetup.java_home}"
        exec "$@"
        """)
    jdk_preparation_script_digest = await Get(
        Digest,
        CreateDigest([
            FileContent(
                JdkSetup.jdk_preparation_script,
                jdk_preparation_script.encode("utf-8"),
                is_executable=True,
            ),
        ]),
    )
    return JdkSetup(
        digest=await Get(
            Digest,
            MergeDigests([
                coursier.digest,
                jdk_preparation_script_digest,
                nailgun.digest,
            ]),
        ),
        nailgun_jar=nailgun.file_name,
    )
Esempio n. 13
0
)
from pants.option.global_options import GlobalOptions
from pants.util.frozendict import FrozenDict
from pants.util.logging import LogLevel
from pants.util.ordered_set import FrozenOrderedSet

logger = logging.getLogger(__name__)

PARSER_SCALA_VERSION = "2.13.7"
SCALAMETA_VERSION = "4.4.30"
CIRCE_VERSION = "0.14.1"

PARSER_SCALA_VERSION_MAJOR_MINOR = ".".join(PARSER_SCALA_VERSION.split(".")[0:2])

SCALAMETA_DEPENDENCIES = [
    Coordinate.from_coord_str(s)
    for s in [
        "org.scalameta:scalameta_2.13:4.4.30",
        "org.scala-lang:scala-library:2.13.7",
        "com.thesamet.scalapb:scalapb-runtime_2.13:0.11.4",
        "org.scalameta:parsers_2.13:4.4.30",
        "org.scala-lang:scala-compiler:2.13.7",
        "net.java.dev.jna:jna:5.8.0",
        "org.scalameta:trees_2.13:4.4.30",
        "org.scalameta:common_2.13:4.4.30",
        "com.lihaoyi:sourcecode_2.13:0.2.7",
        "org.jline:jline:3.20.0",
        "org.scalameta:fastparse-v2_2.13:2.3.1",
        "org.scala-lang.modules:scala-collection-compat_2.13:2.4.4",
        "org.scala-lang:scalap:2.13.7",
        "org.scala-lang:scala-reflect:2.13.7",
Esempio n. 14
0
async def setup_scala_parser_classfiles(
    bash: BashBinary, jdk_setup: JdkSetup
) -> ScalaParserCompiledClassfiles:
    dest_dir = "classfiles"

    parser_source_content = pkgutil.get_data(
        "pants.backend.scala.dependency_inference", "ScalaParser.scala"
    )
    if not parser_source_content:
        raise AssertionError("Unable to find ScalaParser.scala resource.")

    parser_source = FileContent("ScalaParser.scala", parser_source_content)

    tool_classpath, parser_classpath, source_digest = await MultiGet(
        Get(
            MaterializedClasspath,
            MaterializedClasspathRequest(
                prefix="__toolcp",
                artifact_requirements=(
                    ArtifactRequirements(
                        [
                            Coordinate(
                                group="org.scala-lang",
                                artifact="scala-compiler",
                                version=PARSER_SCALA_VERSION,
                            ),
                            Coordinate(
                                group="org.scala-lang",
                                artifact="scala-library",
                                version=PARSER_SCALA_VERSION,
                            ),
                            Coordinate(
                                group="org.scala-lang",
                                artifact="scala-reflect",
                                version=PARSER_SCALA_VERSION,
                            ),
                        ]
                    ),
                ),
            ),
        ),
        Get(
            MaterializedClasspath,
            MaterializedClasspathRequest(
                prefix="__parsercp", artifact_requirements=(SCALA_PARSER_ARTIFACT_REQUIREMENTS,)
            ),
        ),
        Get(
            Digest,
            CreateDigest(
                [
                    parser_source,
                    Directory(dest_dir),
                ]
            ),
        ),
    )

    merged_digest = await Get(
        Digest,
        MergeDigests(
            (
                tool_classpath.digest,
                parser_classpath.digest,
                jdk_setup.digest,
                source_digest,
            )
        ),
    )

    # NB: We do not use nailgun for this process, since it is launched exactly once.
    process_result = await Get(
        ProcessResult,
        Process(
            argv=[
                *jdk_setup.args(bash, tool_classpath.classpath_entries()),
                "scala.tools.nsc.Main",
                "-bootclasspath",
                ":".join(tool_classpath.classpath_entries()),
                "-classpath",
                ":".join(parser_classpath.classpath_entries()),
                "-d",
                dest_dir,
                parser_source.path,
            ],
            input_digest=merged_digest,
            append_only_caches=jdk_setup.append_only_caches,
            env=jdk_setup.env,
            output_directories=(dest_dir,),
            description="Compile Scala parser for dependency inference with scalac",
            level=LogLevel.DEBUG,
        ),
    )
    stripped_classfiles_digest = await Get(
        Digest, RemovePrefix(process_result.output_digest, dest_dir)
    )
    return ScalaParserCompiledClassfiles(digest=stripped_classfiles_digest)
    Coordinate,
    Coordinates,
    CoursierLockfileEntry,
    CoursierResolvedLockfile,
)
from pants.jvm.resolve.coursier_fetch import rules as coursier_fetch_rules
from pants.jvm.resolve.coursier_setup import rules as coursier_setup_rules
from pants.jvm.target_types import JvmArtifact, JvmDependencyLockfile
from pants.jvm.testutil import maybe_skip_jdk_test
from pants.jvm.util_rules import ExtractFileDigest
from pants.jvm.util_rules import rules as util_rules
from pants.testutil.rule_runner import PYTHON_BOOTSTRAP_ENV, QueryRule, RuleRunner, engine_error

HAMCREST_COORD = Coordinate(
    group="org.hamcrest",
    artifact="hamcrest-core",
    version="1.3",
)


@pytest.fixture
def rule_runner() -> RuleRunner:
    rule_runner = RuleRunner(
        rules=[
            *config_files.rules(),
            *coursier_fetch_rules(),
            *coursier_setup_rules(),
            *external_tool_rules(),
            *source_files.rules(),
            *util_rules(),
            QueryRule(CoursierResolvedLockfile, (ArtifactRequirements, )),
Esempio n. 16
0
# To regenerate (e.g. to update the resolved version), run the
# following in a test:
# resolved_lockfile = rule_runner.request(
#     CoursierResolvedLockfile,
#     [
#         MavenRequirements.create_from_maven_coordinates_fields(
#             fields=(),
#             additional_requirements=["junit:junit:4.13.2"],
#         )
#     ],
# )
# The `repr` of the resulting lockfile object can be directly copied
# into code to get the following:
JUNIT4_RESOLVED_LOCKFILE = CoursierResolvedLockfile(entries=(
    CoursierLockfileEntry(
        coord=Coordinate(group="junit", artifact="junit", version="4.13.2"),
        file_name="junit-4.13.2.jar",
        direct_dependencies=Coordinates([
            Coordinate(
                group="org.hamcrest", artifact="hamcrest-core", version="1.3")
        ]),
        dependencies=Coordinates([
            Coordinate(
                group="org.hamcrest", artifact="hamcrest-core", version="1.3")
        ]),
        file_digest=FileDigest(
            fingerprint=
            "8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3",
            serialized_bytes_length=384581,
        ),
    ),
Esempio n. 17
0
async def run_junit_test(
    bash: BashBinary,
    jdk_setup: JdkSetup,
    junit: JUnit,
    test_subsystem: TestSubsystem,
    field_set: JavaTestFieldSet,
) -> TestResult:
    classpath = await Get(Classpath, Addresses([field_set.address]))
    junit_classpath = await Get(
        MaterializedClasspath,
        MaterializedClasspathRequest(
            prefix="__thirdpartycp",
            artifact_requirements=(ArtifactRequirements([
                Coordinate(
                    group="org.junit.platform",
                    artifact="junit-platform-console",
                    version="1.7.2",
                ),
                Coordinate(
                    group="org.junit.jupiter",
                    artifact="junit-jupiter-engine",
                    version="5.7.2",
                ),
                Coordinate(
                    group="org.junit.vintage",
                    artifact="junit-vintage-engine",
                    version="5.7.2",
                ),
            ]), ),
        ),
    )
    merged_digest = await Get(
        Digest,
        MergeDigests((classpath.content.digest, jdk_setup.digest,
                      junit_classpath.digest)),
    )

    reports_dir_prefix = "__reports_dir"
    reports_dir = f"{reports_dir_prefix}/{field_set.address.path_safe_spec}"

    user_classpath_arg = ":".join(classpath.user_classpath_entries())

    process_result = await Get(
        FallibleProcessResult,
        Process(
            argv=[
                *jdk_setup.args(bash, [
                    *classpath.classpath_entries(),
                    *junit_classpath.classpath_entries()
                ]),
                "org.junit.platform.console.ConsoleLauncher",
                *(("--classpath",
                   user_classpath_arg) if user_classpath_arg else ()),
                *(("--scan-class-path",
                   user_classpath_arg) if user_classpath_arg else ()),
                "--reports-dir",
                reports_dir,
                *junit.options.args,
            ],
            input_digest=merged_digest,
            output_directories=(reports_dir, ),
            append_only_caches=jdk_setup.append_only_caches,
            env=jdk_setup.env,
            description=
            f"Run JUnit 5 ConsoleLauncher against {field_set.address}",
            level=LogLevel.DEBUG,
        ),
    )

    xml_result_subset = await Get(
        Digest,
        DigestSubset(process_result.output_digest,
                     PathGlobs([f"{reports_dir_prefix}/**"])))
    xml_results = await Get(
        Snapshot, RemovePrefix(xml_result_subset, reports_dir_prefix))

    return TestResult.from_fallible_process_result(
        process_result,
        address=field_set.address,
        output_setting=test_subsystem.output,
        xml_results=xml_results,
    )
Esempio n. 18
0
async def run_junit_test(
    bash: BashBinary,
    jdk_setup: JdkSetup,
    junit: JUnit,
    test_subsystem: TestSubsystem,
    field_set: JavaTestFieldSet,
) -> TestResult:
    transitive_targets = await Get(TransitiveTargets, TransitiveTargetsRequest([field_set.address]))
    coarsened_targets = await Get(
        CoarsenedTargets, Addresses(t.address for t in transitive_targets.closure)
    )
    lockfile = await Get(
        CoursierResolvedLockfile,
        CoursierLockfileForTargetRequest(Targets(transitive_targets.closure)),
    )
    materialized_classpath = await Get(
        MaterializedClasspath,
        MaterializedClasspathRequest(
            prefix="__thirdpartycp",
            lockfiles=(lockfile,),
            artifact_requirements=(
                ArtifactRequirements(
                    [
                        Coordinate(
                            group="org.junit.platform",
                            artifact="junit-platform-console",
                            version="1.7.2",
                        ),
                        Coordinate(
                            group="org.junit.jupiter",
                            artifact="junit-jupiter-engine",
                            version="5.7.2",
                        ),
                        Coordinate(
                            group="org.junit.vintage",
                            artifact="junit-vintage-engine",
                            version="5.7.2",
                        ),
                    ]
                ),
            ),
        ),
    )
    transitive_user_classfiles = await MultiGet(
        Get(CompiledClassfiles, CompileJavaSourceRequest(component=t)) for t in coarsened_targets
    )
    merged_transitive_user_classfiles_digest = await Get(
        Digest, MergeDigests(classfiles.digest for classfiles in transitive_user_classfiles)
    )
    usercp_relpath = "__usercp"
    prefixed_transitive_user_classfiles_digest = await Get(
        Digest, AddPrefix(merged_transitive_user_classfiles_digest, usercp_relpath)
    )
    merged_digest = await Get(
        Digest,
        MergeDigests(
            (
                prefixed_transitive_user_classfiles_digest,
                materialized_classpath.digest,
                jdk_setup.digest,
            )
        ),
    )
    proc = Process(
        argv=[
            *jdk_setup.args(bash, [materialized_classpath.classpath_arg()]),
            "org.junit.platform.console.ConsoleLauncher",
            "--classpath",
            usercp_relpath,
            "--scan-class-path",
            usercp_relpath,
            *junit.options.args,
        ],
        input_digest=merged_digest,
        description=f"Run JUnit 5 ConsoleLauncher against {field_set.address}",
        level=LogLevel.DEBUG,
    )

    process_result = await Get(
        FallibleProcessResult,
        Process,
        proc,
    )

    return TestResult.from_fallible_process_result(
        process_result,
        address=field_set.address,
        output_setting=test_subsystem.output,
    )
Esempio n. 19
0
from typing import DefaultDict, Sequence
from unittest import mock

import pytest

from pants.engine.fs import EMPTY_DIGEST
from pants.jvm.resolve.coursier_fetch import (
    Coordinate,
    Coordinates,
    CoursierLockfileEntry,
    CoursierResolvedLockfile,
)
from pants.jvm.resolve.key import CoursierResolveKey

coord1 = Coordinate("test", "art1", "1.0.0")
coord2 = Coordinate("test", "art2", "1.0.0")
coord3 = Coordinate("test", "art3", "1.0.0")
coord4 = Coordinate("test", "art4", "1.0.0")
coord5 = Coordinate("test", "art5", "1.0.0")

# No dependencies (coord1)
# 1 direct dependency, more transitive dependencies (coord2)
# 1 where direct dependencies provide no transitive dependencies (coord 4)
# 1 where direct dependencies provide repeated dependencies (coord5)
direct: dict[Coordinate, set[Coordinate]] = {
    coord1: set(),
    coord2: {
        coord3,
    },  # 1, 2, 3, 4, 5
    coord3: {coord1, coord4, coord5},  # 1, 3, 4, 5