-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add integration test for python coverage.
- Loading branch information
1 parent
9a63281
commit 54421e5
Showing
2 changed files
with
192 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
183 changes: 183 additions & 0 deletions
183
src/test/shell/bazel/bazel_coverage_hermetic_py_test.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
#!/bin/bash | ||
# | ||
# Copyright 2015 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; } | ||
|
||
# Fetch hermetic python and register toolchain. | ||
function set_up() { | ||
cat >>WORKSPACE <<EOF | ||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") | ||
http_archive( | ||
name = "rules_python", | ||
sha256 = "cdf6b84084aad8f10bf20b46b77cb48d83c319ebe6458a18e9d2cebf57807cdd", | ||
strip_prefix = "rules_python-0.8.1", | ||
url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.8.1.tar.gz", | ||
) | ||
load("@rules_python//python:repositories.bzl", "python_register_toolchains") | ||
# Load hermetic python toolchain. | ||
python_register_toolchains( | ||
name = "python3_9", | ||
python_version = "3.9", | ||
# Don't register it, though, because we need to set up coverage support. | ||
register_toolchains = False, | ||
) | ||
http_archive( | ||
name = "coverage_linux_x64", | ||
build_file_content = """ | ||
filegroup( | ||
name = "coverage", | ||
srcs = ["coverage/__main__.py"], | ||
data = glob(["coverage/*", "coverage/**/*.py"]), | ||
visibility = ["//visibility:public"], | ||
) | ||
""", | ||
sha256 = "84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3", | ||
type = "zip", | ||
urls = [ | ||
"https://files.pythonhosted.org/packages/74/0d/0f3c522312fd27c32e1abe2fb5c323b583a5c108daf2c26d6e8dfdd5a105/coverage-6.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", | ||
], | ||
) | ||
register_toolchains( | ||
"//:python_toolchain", | ||
) | ||
EOF | ||
} | ||
|
||
# Asserts if the given expected coverage result is included in the given output | ||
# file. | ||
# | ||
# - expected_coverage The expected result that must be included in the output. | ||
# - output_file The location of the coverage output file. | ||
function assert_coverage_result() { | ||
local expected_coverage="${1}"; shift | ||
local output_file="${1}"; shift | ||
|
||
# Replace newlines with commas to facilitate the assertion. | ||
local expected_coverage_no_newlines="$( echo "$expected_coverage" | tr '\n' ',' )" | ||
local output_file_no_newlines="$( cat "$output_file" | tr '\n' ',' )" | ||
|
||
(echo "$output_file_no_newlines" \ | ||
| grep -F "$expected_coverage_no_newlines") \ | ||
|| fail "Expected coverage result | ||
<$expected_coverage> | ||
was not found in actual coverage report: | ||
<$( cat "$output_file" )>" | ||
} | ||
|
||
# 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_py_test_coverage() { | ||
# Set up python toolchain. | ||
cat <<EOF > BUILD | ||
load("@bazel_tools//tools/python:toolchain.bzl", "py_runtime_pair") | ||
py_runtime( | ||
name = "py3_runtime", | ||
coverage_tool = "@coverage_linux_x64//:coverage", | ||
files = ["@python3_9_x86_64-unknown-linux-gnu//:files"], | ||
interpreter = "@python3_9_x86_64-unknown-linux-gnu//:bin/python3", | ||
python_version = "PY3", | ||
) | ||
py_runtime_pair( | ||
name = "python_runtimes", | ||
py2_runtime = None, | ||
py3_runtime = ":py3_runtime", | ||
) | ||
toolchain( | ||
name = "python_toolchain", | ||
exec_compatible_with = [ | ||
"@platforms//os:linux", | ||
"@platforms//cpu:x86_64", | ||
], | ||
toolchain = ":python_runtimes", | ||
toolchain_type = "@bazel_tools//tools/python:toolchain_type", | ||
) | ||
EOF | ||
# Add a py_library and test. | ||
cat <<EOF >> BUILD | ||
py_library( | ||
name = "hello", | ||
srcs = ["hello.py"], | ||
) | ||
py_test( | ||
name = "hello_test", | ||
srcs = ["hello_test.py"], | ||
deps = [":hello"], | ||
) | ||
EOF | ||
cat <<EOF > hello.py | ||
def Hello(): | ||
print("Hello, world!") | ||
def Goodbye(): | ||
print("Goodbye, world!") | ||
EOF | ||
cat <<EOF > hello_test.py | ||
import unittest | ||
import hello | ||
class Tests(unittest.TestCase): | ||
def testHello(self): | ||
hello.Hello() | ||
if __name__ == "__main__": | ||
unittest.main() | ||
EOF | ||
cat <<EOF > expected.dat | ||
SF:hello.py | ||
FNF:0 | ||
FNH:0 | ||
DA:1,1,fi+A0ud2xABMExsbhdW38w | ||
DA:2,1,3qA2I6CcUyJmcd1vpeVcRA | ||
DA:4,1,nFnrj5CwYCqkvbVhPUFVVw | ||
DA:5,0,RmWioilSA3bI5NbLlwiuSA | ||
LH:3 | ||
LF:4 | ||
end_of_record | ||
EOF | ||
} | ||
|
||
function test_py_test_coverage() { | ||
set_up_py_test_coverage | ||
bazel coverage --test_output=all //:hello_test &>$TEST_log || fail "Coverage for //:hello_test failed" | ||
local coverage_file_path="$( get_coverage_file_path_from_test_log )" | ||
diff expected.dat "$coverage_file_path" >> $TEST_log | ||
cmp expected.dat "$coverage_file_path" || fail "Coverage output file is different than the expected file for py_library." | ||
} | ||
|
||
run_suite "test tests" |