Skip to content

Commit

Permalink
feat: implement bats test runner (#699)
Browse files Browse the repository at this point in the history
  • Loading branch information
thesayyn authored Dec 20, 2023
1 parent 8d805e1 commit 4f6b4bd
Show file tree
Hide file tree
Showing 22 changed files with 502 additions and 3 deletions.
4 changes: 3 additions & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ bazel_lib_toolchains.yq()
bazel_lib_toolchains.coreutils()
bazel_lib_toolchains.tar()
bazel_lib_toolchains.expand_template()
use_repo(bazel_lib_toolchains, "bsd_tar_toolchains", "copy_directory_toolchains", "copy_to_directory_toolchains", "coreutils_toolchains", "expand_template_toolchains", "jq_toolchains", "yq_toolchains")
bazel_lib_toolchains.bats()
use_repo(bazel_lib_toolchains, "bats_toolchains", "bsd_tar_toolchains", "copy_directory_toolchains", "copy_to_directory_toolchains", "coreutils_toolchains", "expand_template_toolchains", "jq_toolchains", "yq_toolchains")

register_toolchains(
"@copy_directory_toolchains//:all",
Expand All @@ -31,6 +32,7 @@ register_toolchains(
"@yq_toolchains//:all",
"@coreutils_toolchains//:all",
"@expand_template_toolchains//:all",
"@bats_toolchains//:all",
# Expand bsd_tar_toolchains
"@bsd_tar_toolchains//:linux_amd64_toolchain",
"@bsd_tar_toolchains//:linux_arm64_toolchain",
Expand Down
5 changes: 5 additions & 0 deletions docs/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,9 @@ stardoc_with_diff_test(
bzl_library_target = "//lib:strings",
)

stardoc_with_diff_test(
name = "bats",
bzl_library_target = "//lib:bats",
)

update_docs()
25 changes: 25 additions & 0 deletions docs/bats.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions docs/repositories.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions e2e/smoke/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
load("@aspect_bazel_lib//lib:bats.bzl", "bats_test")
load("@aspect_bazel_lib//lib:copy_directory.bzl", "copy_directory")
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
load("@aspect_bazel_lib//lib:diff_test.bzl", "diff_test")
Expand Down Expand Up @@ -91,3 +92,10 @@ tar(
srcs = [],
mtree = [],
)

bats_test(
name = "bats",
srcs = [
"basic.bats",
],
)
8 changes: 8 additions & 0 deletions e2e/smoke/basic.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
bats_load_library "bats-support"
bats_load_library "bats-assert"

@test 'basic' {
run echo 'have'
assert_output 'have'
}

5 changes: 4 additions & 1 deletion internal_deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Users should *not* need to install these. If users see a load()
statement from these, that's a bug in our distribution.
"""

load("//lib:repositories.bzl", "register_coreutils_toolchains", "register_jq_toolchains", "register_tar_toolchains", "register_yq_toolchains")
load("//lib:repositories.bzl", "register_bats_toolchains", "register_coreutils_toolchains", "register_jq_toolchains", "register_tar_toolchains", "register_yq_toolchains")
load("//lib:utils.bzl", http_archive = "maybe_http_archive")

# buildifier: disable=unnamed-macro
Expand Down Expand Up @@ -72,3 +72,6 @@ def bazel_lib_internal_deps():
register_yq_toolchains()
register_coreutils_toolchains()
register_tar_toolchains()
register_bats_toolchains(
libraries = ["@aspect_bazel_lib//lib/tests/bats/bats-custom:custom"],
)
14 changes: 13 additions & 1 deletion lib/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,16 @@ toolchain_type(
name = "tar_toolchain_type",
)

toolchain_type(
name = "bats_toolchain_type",
)

bzl_library(
name = "expand_make_vars",
srcs = ["expand_make_vars.bzl"],
deps = [
":expand_template",
"//lib/private:expand_locations",
"//lib/private:expand_variables",
],
)

Expand Down Expand Up @@ -235,6 +240,7 @@ bzl_library(
srcs = ["repositories.bzl"],
deps = [
":utils",
"//lib/private:bats_toolchain",
"//lib/private:copy_directory_toolchain",
"//lib/private:copy_to_directory_toolchain",
"//lib/private:coreutils_toolchain",
Expand Down Expand Up @@ -295,3 +301,9 @@ bzl_library(
srcs = ["windows_utils.bzl"],
deps = ["//lib/private:paths"],
)

bzl_library(
name = "bats",
srcs = ["bats.bzl"],
deps = ["//lib/private:bats"],
)
5 changes: 5 additions & 0 deletions lib/bats.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"Bats test runner"

load("//lib/private:bats.bzl", _bats_test = "bats_test")

bats_test = _bats_test
16 changes: 16 additions & 0 deletions lib/extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

load(
"@aspect_bazel_lib//lib:repositories.bzl",
"DEFAULT_BATS_CORE_VERSION",
"DEFAULT_BATS_REPOSITORY",
"DEFAULT_COPY_DIRECTORY_REPOSITORY",
"DEFAULT_COPY_TO_DIRECTORY_REPOSITORY",
"DEFAULT_COREUTILS_REPOSITORY",
Expand All @@ -12,6 +14,7 @@ load(
"DEFAULT_TAR_REPOSITORY",
"DEFAULT_YQ_REPOSITORY",
"DEFAULT_YQ_VERSION",
"register_bats_toolchains",
"register_copy_directory_toolchains",
"register_copy_to_directory_toolchains",
"register_coreutils_toolchains",
Expand Down Expand Up @@ -94,6 +97,15 @@ def _toolchains_extension_impl(mctx):
get_version_fn = lambda attr: None,
)

extension_utils.toolchain_repos_bfs(
mctx = mctx,
get_tag_fn = lambda tags: tags.bats,
toolchain_name = "bats",
default_repository = DEFAULT_BATS_REPOSITORY,
toolchain_repos_fn = lambda name, version: register_bats_toolchains(name = name, core_version = version, register = False),
get_version_fn = lambda attr: attr.core_version,
)

toolchains = module_extension(
implementation = _toolchains_extension_impl,
tag_classes = {
Expand All @@ -104,5 +116,9 @@ toolchains = module_extension(
"coreutils": tag_class(attrs = {"name": attr.string(default = DEFAULT_COREUTILS_REPOSITORY), "version": attr.string(default = DEFAULT_COREUTILS_VERSION)}),
"tar": tag_class(attrs = {"name": attr.string(default = DEFAULT_TAR_REPOSITORY)}),
"expand_template": tag_class(attrs = {"name": attr.string(default = DEFAULT_EXPAND_TEMPLATE_REPOSITORY)}),
"bats": tag_class(attrs = {
"name": attr.string(default = DEFAULT_BATS_REPOSITORY),
"core_version": attr.string(default = DEFAULT_BATS_CORE_VERSION),
}),
},
)
17 changes: 17 additions & 0 deletions lib/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,23 @@ bzl_library(
deps = ["@aspect_bazel_lib//lib:paths"],
)

bzl_library(
name = "bats",
srcs = ["bats.bzl"],
visibility = ["//lib:__subpackages__"],
deps = [
":expand_locations",
":expand_variables",
"@aspect_bazel_lib//lib:paths",
],
)

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

bzl_library(
name = "copy_common",
srcs = ["copy_common.bzl"],
Expand Down
90 changes: 90 additions & 0 deletions lib/private/bats.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"bats_test"

load("//lib:paths.bzl", "BASH_RLOCATION_FUNCTION", "to_rlocation_path")
load(":expand_locations.bzl", "expand_locations")
load(":expand_variables.bzl", "expand_variables")

_RUNNER_TMPL = """#!/usr/bin/env bash
set -o errexit -o nounset -o pipefail
{BASH_RLOCATION_FUNCTION}
readonly core_path="$(rlocation {core})"
readonly bats="$core_path/bin/bats"
readonly libs=( {libraries} )
{envs}
NEW_LIBS=()
for lib in "${{libs[@]}}"; do
NEW_LIBS+=( $(cd "$(rlocation $lib)/.." && pwd) )
done
export BATS_LIB_PATH=$(
IFS=:
echo "${{NEW_LIBS[*]}}"
)
export BATS_TEST_TIMEOUT="$TEST_TIMEOUT"
export BATS_TMPDIR="$TEST_TMPDIR"
exec $bats {tests} $@
"""

_ENV_SET = """export {var}=\"{value}\""""

def _bats_test_impl(ctx):
toolchain = ctx.toolchains["@aspect_bazel_lib//lib:bats_toolchain_type"]
batsinfo = toolchain.batsinfo

envs = []
for (key, value) in ctx.attr.env.items():
envs.append(_ENV_SET.format(
var = key,
value = " ".join([expand_variables(ctx, exp, attribute_name = "env") for exp in expand_locations(ctx, value, ctx.attr.data).split(" ")]),
))

runner = ctx.actions.declare_file("%s_bats.sh" % ctx.label.name)
ctx.actions.write(
output = runner,
content = _RUNNER_TMPL.format(
core = to_rlocation_path(ctx, batsinfo.core),
libraries = " ".join([to_rlocation_path(ctx, lib) for lib in batsinfo.libraries]),
tests = " ".join([test.short_path for test in ctx.files.srcs]),
envs = "\n".join(envs),
BASH_RLOCATION_FUNCTION = BASH_RLOCATION_FUNCTION,
),
is_executable = True,
)

runfiles = ctx.runfiles(ctx.files.srcs + ctx.files.data)
runfiles = runfiles.merge(toolchain.default.default_runfiles)
runfiles = runfiles.merge(ctx.attr._runfiles.default_runfiles)

return DefaultInfo(
executable = runner,
runfiles = runfiles,
)

bats_test = rule(
implementation = _bats_test_impl,
attrs = {
"srcs": attr.label_list(
allow_files = [".bats"],
doc = "Test files",
),
"data": attr.label_list(
allow_files = True,
doc = "Runtime dependencies of the test.",
),
"env": attr.string_dict(
doc = """Environment variables of the action.
Subject to [$(location)](https://bazel.build/reference/be/make-variables#predefined_label_variables)
and ["Make variable"](https://bazel.build/reference/be/make-variables) substitution.
""",
),
"_runfiles": attr.label(default = "@bazel_tools//tools/bash/runfiles"),
},
toolchains = ["@aspect_bazel_lib//lib:bats_toolchain_type"],
test = True,
)
Loading

0 comments on commit 4f6b4bd

Please sign in to comment.