| #!/bin/bash |
| # |
| # Copyright 2021 The Bazel Authors. All rights reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| set -eu |
| |
| # Load the test setup defined in the parent directory |
| CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| source "${CURRENT_DIR}/../integration_test_setup.sh" \ |
| || { echo "integration_test_setup.sh not found!" >&2; exit 1; } |
| |
| # Returns the path of the code coverage report that was generated by Bazel by |
| # looking at the current $TEST_log. The method fails if TEST_log does not |
| # contain any coverage report for a passed test. |
| function get_coverage_file_path_from_test_log() { |
| local ending_part="$(sed -n -e '/PASSED/,$p' "$TEST_log")" |
| |
| local coverage_file_path=$(grep -Eo "/[/a-zA-Z0-9\.\_\-]+\.dat$" <<< "$ending_part") |
| [[ -e "$coverage_file_path" ]] || fail "Coverage output file does not exist!" |
| echo "$coverage_file_path" |
| } |
| |
| function set_up() { |
| touch WORKSPACE |
| } |
| |
| function test_starlark_rule_without_lcov_merger() { |
| cat <<EOF > rules.bzl |
| def _impl(ctx): |
| output = ctx.actions.declare_file(ctx.attr.name) |
| ctx.actions.write(output, """\ |
| #!/bin/bash |
| |
| if [[ ! -r extra ]]; then |
| echo "extra file not found" >&2 |
| exit 1 |
| fi |
| |
| if [[ -z \$COVERAGE ]]; then |
| echo "COVERAGE environment variable not set, coverage not run." |
| exit 1 |
| fi |
| """, is_executable = True) |
| extra_file = ctx.actions.declare_file("extra") |
| ctx.actions.write(extra_file, "extra") |
| return [DefaultInfo(executable=output, runfiles=ctx.runfiles(files=[extra_file]))] |
| |
| custom_test = rule( |
| implementation = _impl, |
| test = True, |
| ) |
| EOF |
| |
| cat <<EOF > BUILD |
| load(":rules.bzl", "custom_test") |
| |
| custom_test(name = "foo_test") |
| EOF |
| bazel coverage //:foo_test --combined_report=lcov > $TEST_log \ |
| || fail "Coverage run failed but should have succeeded." |
| } |
| |
| function test_starlark_rule_without_lcov_merger_failing_test() { |
| cat <<EOF > rules.bzl |
| def _impl(ctx): |
| executable = ctx.actions.declare_file(ctx.attr.name) |
| ctx.actions.write(executable, "exit 1", is_executable = True) |
| return [ |
| DefaultInfo( |
| executable = executable, |
| ) |
| ] |
| custom_test = rule( |
| implementation = _impl, |
| test = True, |
| ) |
| EOF |
| |
| cat <<EOF > BUILD |
| load(":rules.bzl", "custom_test") |
| |
| custom_test(name = "foo_test") |
| EOF |
| if bazel coverage //:foo_test > $TEST_log; then |
| fail "Coverage run succeeded but should have failed." |
| fi |
| } |
| |
| |
| function test_starlark_rule_with_custom_lcov_merger() { |
| |
| cat <<EOF > lcov_merger.sh |
| for var in "\$@" |
| do |
| if [[ "\$var" == "--output_file="* ]]; then |
| path="\${var##--output_file=}" |
| mkdir -p "\$(dirname \$path)" |
| echo lcov_merger_called >> \$path |
| exit 0 |
| fi |
| done |
| EOF |
| chmod +x lcov_merger.sh |
| |
| cat <<EOF > rules.bzl |
| def _impl(ctx): |
| output = ctx.actions.declare_file(ctx.attr.name) |
| ctx.actions.write(output, "", is_executable = True) |
| return [DefaultInfo(executable=output)] |
| |
| custom_test = rule( |
| implementation = _impl, |
| test = True, |
| attrs = { |
| "_lcov_merger": attr.label(default = ":lcov_merger", cfg = "exec"), |
| }, |
| ) |
| EOF |
| |
| cat <<EOF > BUILD |
| load(":rules.bzl", "custom_test") |
| |
| sh_binary( |
| name = "lcov_merger", |
| srcs = ["lcov_merger.sh"], |
| ) |
| custom_test(name = "foo_test") |
| EOF |
| |
| bazel coverage --test_output=all //:foo_test --combined_report=lcov > $TEST_log \ |
| || fail "Coverage run failed but should have succeeded." |
| |
| local coverage_file_path="$( get_coverage_file_path_from_test_log )" |
| cat $coverage_file_path |
| grep "lcov_merger_called" "$coverage_file_path" \ |
| || fail "Coverage report did not contain evidence of custom lcov_merger." |
| } |
| |
| function test_starlark_rule_with_configuration_field_lcov_merger_coverage_enabled() { |
| |
| cat <<EOF > lcov_merger.sh |
| for var in "\$@" |
| do |
| if [[ "\$var" == "--output_file="* ]]; then |
| path="\${var##--output_file=}" |
| mkdir -p "\$(dirname \$path)" |
| echo lcov_merger_called >> \$path |
| exit 0 |
| fi |
| done |
| EOF |
| chmod +x lcov_merger.sh |
| |
| cat <<EOF > rules.bzl |
| def _impl(ctx): |
| output = ctx.actions.declare_file(ctx.attr.name) |
| ctx.actions.write(output, "", is_executable = True) |
| return [DefaultInfo(executable=output)] |
| |
| custom_test = rule( |
| implementation = _impl, |
| test = True, |
| attrs = { |
| "_lcov_merger": attr.label( |
| default = configuration_field(fragment = "coverage", name = "output_generator"), |
| cfg = "exec" |
| ), |
| }, |
| fragments = ["coverage"], |
| ) |
| EOF |
| |
| cat <<EOF > BUILD |
| load(":rules.bzl", "custom_test") |
| |
| sh_binary( |
| name = "lcov_merger", |
| srcs = ["lcov_merger.sh"], |
| ) |
| custom_test(name = "foo_test") |
| EOF |
| |
| bazel coverage --test_output=all //:foo_test --combined_report=lcov --coverage_output_generator=//:lcov_merger > $TEST_log \ |
| || fail "Coverage run failed but should have succeeded." |
| |
| local coverage_file_path="$( get_coverage_file_path_from_test_log )" |
| cat $coverage_file_path |
| grep "lcov_merger_called" "$coverage_file_path" \ |
| || fail "Coverage report did not contain evidence of custom lcov_merger." |
| } |
| |
| function test_starlark_rule_with_configuration_field_lcov_merger_coverage_disabled() { |
| |
| cat <<EOF > rules.bzl |
| def _impl(ctx): |
| if ctx.attr._lcov_merger: |
| fail("Expected _lcov_merger to be None if coverage is not collected") |
| output = ctx.actions.declare_file(ctx.attr.name) |
| ctx.actions.write(output, "", is_executable = True) |
| return [DefaultInfo(executable=output)] |
| |
| custom_test = rule( |
| implementation = _impl, |
| test = True, |
| attrs = { |
| "_lcov_merger": attr.label( |
| default = configuration_field(fragment = "coverage", name = "output_generator"), |
| cfg = "exec" |
| ), |
| }, |
| fragments = ["coverage"], |
| ) |
| EOF |
| |
| cat <<EOF > BUILD |
| load(":rules.bzl", "custom_test") |
| |
| custom_test(name = "foo_test") |
| EOF |
| |
| bazel test --test_output=all //:foo_test > $TEST_log \ |
| || fail "Test run failed but should have succeeded." |
| } |
| |
| run_suite "test tests" |