Skip to content

Commit

Permalink
bazel: making progress with the rules
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelnaranjo committed Mar 11, 2024
1 parent ad7a8ec commit 841621b
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 124 deletions.
6 changes: 2 additions & 4 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,17 @@ bazel_dep(name = "rules_java", version = "7.4.0")
bazel_dep(name = "rules_jvm_external", version = "6.0")

maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")

maven.install(
name = "maven_pitest",
artifacts = [
"org.pitest:pitest:1.15.8",
"org.pitest:pitest-entry:1.15.8",
"org.pitest:pitest-command-line:1.15.8",
"org.pitest:pitest-junit5-plugin:1.2.1"
"org.pitest:pitest-junit5-plugin:1.2.1",
],
fetch_sources = False,
lock_file = "//:maven_install.json",
name = "maven_pitest"
)

use_repo(
maven,
"maven_pitest",
Expand Down
1 change: 1 addition & 0 deletions e2e/smoke/.bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ common --java_runtime_version=remotejdk_17
common --java_language_version=17
common --tool_java_runtime_version=remotejdk_17
common --tool_java_language_version=17
test --test_output=errors
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("@rules_java//java:defs.bzl", "java_library")
load("@com_bookingcom_rules_pitest//pitest:defs.bzl", "java_pitest_test")

java_library(
name = "example",
Expand All @@ -14,3 +15,9 @@ java_library(
],
visibility = ["//:__subpackages__"],
)

filegroup(
name = "java_srcs",
srcs = glob(["*.java"]),
visibility = ["//:__subpackages__"],
)
35 changes: 35 additions & 0 deletions e2e/smoke/sample-from-upstream/src/test/com/example/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
load("@com_bookingcom_rules_pitest//pitest:defs.bzl", "java_pitest_test")
load("@contrib_rules_jvm//java:defs.bzl", "java_test_suite")

java_test_suite(
Expand All @@ -18,3 +19,37 @@ java_test_suite(
"@maven//:pl_pragmatists_JUnitParams",
],
)

java_pitest_test(
name = "mutate",
srcs = [
"BeforeAfterClassTest.java",
"CoveredByABeforeAfterClass.java",
"CoveredByJUnitThreeSuite.java",
"HasExcludedMethodsTestee.java",
"HasExcludedMethodsTesteeTest.java",
"JUnitParamsTest.java",
"LineNumbersSpanBlocks.java",
"TheoryTest.java",
"//sample-from-upstream/src/main/java/com/example:java_srcs",
],
args = [
"--verbose",
"--targetTests",
"com.example.*",
"--verbosity",
"10000",
"--mutableCodePaths",
"sample-from-upstream/src/main/java",
"--classPath",
"",
],
src_dirs = [
"sample-from-upstream/src/main/java/com/example",
],
target = ":example",
target_classes = ["com.example.*"],
runtime_deps = [
"@com_bookingcom_rules_pitest//pitest:org_pitest_pitest_junit5_plugin",
],
)
25 changes: 9 additions & 16 deletions pitest/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,20 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
# For stardoc to reference the files
exports_files(["defs.bzl"])

# This is the target rule authors should put in their "toolchains"
# attribute in order to get a runtime for the correct platform.
# See https://docs.bazel.build/versions/main/toolchains.html#writing-rules-that-use-toolchains
toolchain_type(
name = "toolchain_type",
bzl_library(
name = "defs",
srcs = ["defs.bzl"],
visibility = ["//visibility:public"],
)

bzl_library(
name = "repositories",
srcs = ["repositories.bzl"],
alias(
name = "org_pitest_pitest_command_line",
actual = "@maven_pitest//:org_pitest_pitest_command_line",
visibility = ["//visibility:public"],
deps = [
"//pitest/private:versions",
"@bazel_tools//tools/build_defs/repo:http.bzl",
"@bazel_tools//tools/build_defs/repo:utils.bzl",
],
)

bzl_library(
name = "defs",
srcs = ["defs.bzl"],
alias(
name = "org_pitest_pitest_junit5_plugin",
actual = "@maven_pitest//:org_pitest_pitest_junit5_plugin",
visibility = ["//visibility:public"],
)
6 changes: 3 additions & 3 deletions pitest/defs.bzl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"Public API re-exports"

def example():
"""This is an example"""
pass
load("//pitest/private:rules.bzl", _java_pitest_test = "java_pitest_test")

java_pitest_test = _java_pitest_test
11 changes: 0 additions & 11 deletions pitest/private/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("@rules_java//java:defs.bzl", "java_binary")

bzl_library(
name = "versions",
srcs = ["versions.bzl"],
visibility = ["//pitest:__subpackages__"],
)

java_binary(
name = "pitest-cli",
runtime_deps = [
"@maven_pitest//:org_pitest_pitest_command_line"
],
main_class = "org.pitest.mutationtest.commandline.MutationCoverageReport",
visibility = ["//pitest:__subpackages__"]
)

96 changes: 77 additions & 19 deletions pitest/private/rules.bzl
Original file line number Diff line number Diff line change
@@ -1,19 +1,77 @@
def _pitest_impl(ctx):
print("inside rule", ctx)
pass

pitest = rule(
implemenation = _pitest_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
"targetClasses": attr.string_list(),
"outputFormat": attr.string_list(default=["HTML"]),
"outputEncoding": attr.string(default = "UTF-8"),
"target": attr.label(mandatory = True, cfg = "exec"),
"extraArguments": attr.string_dict(default = {}),
"_pitest_cli": attr.label(
default = "//pitest/private:pitest-cli",
cfg = "exec"
),
}
)
load("@rules_java//java:defs.bzl", "java_test")

# Common package prefixes, in the order we want to check for them
_PREFIXES = (".com.", ".org.", ".net.", ".io.", ".ai.", ".co.", ".me.")

# By default bazel computes the name of test classes based on the
# standard Maven directory structure, which we may not always use,
# so try to compute the correct package name.
#
# this method is based on: https://github.com/bazel-contrib/rules_jvm/blob/f0a9a36e881f4813f50656eaee81f9988b2b7d29/java/private/package.bzl#L7
def _get_package_name(prefixes = []):
pkg = native.package_name().replace("/", ".")
if len(prefixes) == 0:
prefixes = _PREFIXES

for prefix in prefixes:
idx = pkg.find(prefix)
if idx != -1:
return pkg[idx + 1:] + "."

return ""

def java_pitest_test(
name,
test_class = None,
package_prefixes = [],
runtime_deps = [],
args = [],
srcs = [],
src_dirs = [],
data = [],
target = None,
target_classes = [],
**kwargs):
"""Runs pitest test using Bazel.
This is designed to be a drop-in replacement for `java_test`, but
rather than using a JUnit4 runner it provides support for using
pitest directly. The arguments are the same as used by `java_test`.
Args:
name: The name of the test.
test_class: The Java class to be loaded by the test runner. If not
specified, the class name will be inferred from a combination of
the current bazel package and the `name` attribute.
runtime_deps: Additional runtime dependencies for the test.
**kwargs: Aditional flags to the test
package_prefixes: List of prefixes for your maven targets
"""
if test_class:
clazz = test_class
else:
clazz = _get_package_name(package_prefixes) + name

src_dirs = [native.package_name()] + src_dirs

args = list(args)
args += [
"--reportDir",
"report-dir",
"--sourceDirs",
",".join(src_dirs),
"--targetClasses",
",".join(target_classes),
]

java_test(
name = name,
main_class = "org.pitest.mutationtest.commandline.MutationCoverageReport",
test_class = clazz,
runtime_deps = runtime_deps + [
"@com_bookingcom_rules_pitest//pitest:org_pitest_pitest_command_line",
],
data = srcs + data + [target],
args = args,
**kwargs
)
71 changes: 0 additions & 71 deletions pitest/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ See https://docs.bazel.build/versions/main/skylark/deploying.html#dependencies

load("@bazel_tools//tools/build_defs/repo:http.bzl", _http_archive = "http_archive")
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
load("//pitest/private:toolchains_repo.bzl", "PLATFORMS", "toolchains_repo")
load("//pitest/private:versions.bzl", "TOOL_VERSIONS")

def http_archive(name, **kwargs):
maybe(_http_archive, name = name, **kwargs)
Expand All @@ -29,72 +27,3 @@ def rules_pitest_dependencies():
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
],
)

########
# Remaining content of the file is only used to support toolchains.
########
_DOC = "Fetch external tools needed for pitest toolchain"
_ATTRS = {
"pitest_version": attr.string(mandatory = True, values = TOOL_VERSIONS.keys()),
"platform": attr.string(mandatory = True, values = PLATFORMS.keys()),
}

def _pitest_repo_impl(repository_ctx):
url = "https://github.com/bookingcom/rules_pitest/releases/download/v{0}/pitest-{1}.zip".format(
repository_ctx.attr.pitest_version,
repository_ctx.attr.platform,
)
repository_ctx.download_and_extract(
url = url,
integrity = TOOL_VERSIONS[repository_ctx.attr.pitest_version][repository_ctx.attr.platform],
)
build_content = """# Generated by pitest/repositories.bzl
load("@com_bookingcom_rules_pitest//pitest:toolchain.bzl", "pitest_toolchain")
pitest_toolchain(
name = "pitest_toolchain",
target_tool = select({
"@bazel_tools//src/conditions:host_windows": "pitest_tool.exe",
"//conditions:default": "pitest_tool",
}),
)
"""

# Base BUILD file for this repository
repository_ctx.file("BUILD.bazel", build_content)

pitest_repositories = repository_rule(
_pitest_repo_impl,
doc = _DOC,
attrs = _ATTRS,
)

# Wrapper macro around everything above, this is the primary API
def pitest_register_toolchains(name, register = True, **kwargs):
"""Convenience macro for users which does typical setup.
- create a repository for each built-in platform like "pitest_linux_amd64" -
this repository is lazily fetched when node is needed for that platform.
- TODO: create a convenience repository for the host platform like "pitest_host"
- create a repository exposing toolchains for each platform like "pitest_platforms"
- register a toolchain pointing at each platform
Users can avoid this macro and do these steps themselves, if they want more control.
Args:
name: base name for all created repos, like "pitest1_14"
register: whether to call through to native.register_toolchains.
Should be True for WORKSPACE users, but false when used under bzlmod extension
**kwargs: passed to each node_repositories call
"""
for platform in PLATFORMS.keys():
pitest_repositories(
name = name + "_" + platform,
platform = platform,
**kwargs
)
if register:
native.register_toolchains("@%s_toolchains//:%s_toolchain" % (name, platform))

toolchains_repo(
name = name + "_toolchains",
user_repository_name = name,
)

0 comments on commit 841621b

Please sign in to comment.