"bats_test" load("//lib:paths.bzl", "BASH_RLOCATION_FUNCTION", "to_rlocation_path") load("//lib:windows_utils.bzl", "create_windows_native_launcher_script") load(":expand_locations.bzl", "expand_locations") load(":expand_variables.bzl", "expand_variables") _LAUNCHER_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 {key}=\"{value}\"""" def _bats_test_impl(ctx): toolchain = ctx.toolchains["@aspect_bazel_lib//lib:bats_toolchain_type"] batsinfo = toolchain.batsinfo is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]) envs = [] for (key, value) in ctx.attr.env.items(): envs.append(_ENV_SET.format( key = key, value = " ".join([expand_variables(ctx, exp, attribute_name = "env") for exp in expand_locations(ctx, value, ctx.attr.data).split(" ")]), )) # See https://www.msys2.org/wiki/Porting/: # > Setting MSYS2_ARG_CONV_EXCL=* prevents any path transformation. if is_windows: envs.append(_ENV_SET.format( key = "MSYS2_ARG_CONV_EXCL", value = "*", )) envs.append(_ENV_SET.format( key = "MSYS_NO_PATHCONV", value = "1", )) bash_launcher = ctx.actions.declare_file("%s_bats.sh" % ctx.label.name) ctx.actions.write( output = bash_launcher, content = _LAUNCHER_TMPL.format( core = to_rlocation_path(ctx, batsinfo.core), libraries = " ".join([to_rlocation_path(ctx, lib) for lib in batsinfo.libraries]), tests = " ".join(["$(rlocation %s)" % to_rlocation_path(ctx, test) for test in ctx.files.srcs]), envs = "\n".join(envs), BASH_RLOCATION_FUNCTION = BASH_RLOCATION_FUNCTION, ), is_executable = True, ) launcher = create_windows_native_launcher_script(ctx, bash_launcher) if is_windows else bash_launcher runfiles = ctx.runfiles(ctx.files.srcs + ctx.files.data + [bash_launcher]) runfiles = runfiles.merge(toolchain.default.default_runfiles) runfiles = runfiles.merge(ctx.attr._runfiles.default_runfiles) return DefaultInfo( executable = launcher, 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"), "_windows_constraint": attr.label(default = "@platforms//os:windows"), }, toolchains = [ "@aspect_bazel_lib//lib:bats_toolchain_type", "@bazel_tools//tools/sh:toolchain_type", ], test = True, )